Was ist falsch an meinen For-Schleifen? Ich bekomme Warnungen: Vergleich zwischen vorzeichenbehafteten und vorzeichenlosen Integerausdrücken [-Wsign-compare]

7
%Vor%     
code511788465541441 02.11.2011, 17:49
quelle

9 Antworten

13
  

Warum gibt es eine Warnung mit -Wsign-compare ?

Wie der Name der Warnung und ihr Text andeuten, besteht das Problem darin, dass Sie eine vorzeichenbehaftete und eine vorzeichenlose Ganzzahl vergleichen. Es wird allgemein angenommen, dass dies ein Unfall ist.

Um diese Warnung zu vermeiden, müssen Sie lediglich sicherstellen, dass beide Operanden von < (oder einem anderen Vergleichsoperator) entweder signiert oder beide vorzeichenlos sind.

  

Wie könnte ich es besser machen?

Das idiomatische Schreiben einer for -Schleife besteht darin, sowohl den Zähler als auch das Limit in der ersten Anweisung zu initialisieren:

%Vor%

Dies spart die Neuberechnung von size() bei jeder Iteration.

Sie könnten (und sollten wahrscheinlich) Iteratoren anstelle von Indizes verwenden:

%Vor%

auto ist hier eine Abkürzung für std::vector<int>::iterator . Iteratoren funktionieren für alle Arten von Containern, während Indizes auf C-Arrays, deque und vector beschränkt sind.

    
Matthieu M. 02.11.2011, 18:02
quelle
5

Dies liegt daran, dass die Funktion .size () der Vektorklasse nicht vom Typ int ist, sondern vom Typ vector :: size_type

Benutze das oder auto i = 0u und die Nachrichten sollten verschwinden.

    
inf 02.11.2011 17:52
quelle
3

int ist standardmäßig signiert - es entspricht dem Schreiben von signed int . Der Grund dafür, dass Sie eine Warnung erhalten, ist, dass size() eine vector::size_type zurückgibt, die mehr als wahrscheinlich vorzeichenlos ist.

Dies ist potentiell gefährlich, da signed int und unsigned int unterschiedliche Wertebereiche enthalten. signed int kann Werte zwischen –2147483648 bis 2147483647 enthalten, während ein unsigned int Werte zwischen 0 bis 4294967295 speichern kann (unter der Annahme, dass int 32 Bits ist).

    
Marlon 02.11.2011 18:05
quelle
2

Ihre Variable i ist eine Ganzzahl, während die size Elementfunktion von Vektor, die ein Allocator::size_type zurückgibt, sehr wahrscheinlich ein size_t zurückgibt, das fast immer als vorzeichenloses int einiger Größe implementiert wird.

    
Michael Goldshteyn 02.11.2011 17:52
quelle
2

Machen Sie Ihre int i als size_type i .
std::vector::size() gibt size_type zurück, was eine unsigned int ist, da die Größe nicht -ve sein kann.
Die Warnung ist offensichtlich, weil Sie vorzeichenbehaftete Ganzzahl mit vorzeichenloser Ganzzahl vergleichen.

    
Alok Save 02.11.2011 17:53
quelle
2

Beantworten nach so vielen Antworten, aber niemand bemerkte das Ende der Schleife .. Also, hier ist meine vollständige Antwort:

  1. Um die Warnung zu entfernen, ändern Sie den Typ i in unsigned , auto (für C ++ 11) oder std::vector< your_type >::size_type
  2. Ihre for Schleifen werden seg-fault, wenn Sie diese i als Index benutzen - Sie müssen eine Schleife von 0 bis size-1 inklusive machen. Also, ändere es in for( std::vector< your_type >::size_type i = 0; i < vector_xxx.size(); ++i )
    (beachte < , nicht <= ; mein Ratschlag ist nicht, <= mit .begin() - 1 zu verwenden, weil du einen Vektor mit der Größe 0 haben kannst und du wirst Probleme damit haben :) ).
  3. Um dies generischer zu machen, können Sie% ce_de% s verwenden, wenn Sie einen Container verwenden und ihn durchlaufen. Dies erleichtert die zukünftige Änderung des Containertyps (wenn Sie die genaue Position natürlich nicht als Nummer benötigen). Also würde ich es so schreiben:
%Vor%     
Kiril Kirov 02.11.2011 18:00
quelle
2

Sie erhalten diese Warnung, weil die Größe eines Containers in C ++ ein vorzeichenloser Typ ist und das Mischen von Typen mit Vorzeichen / Vorzeichen gefährlich ist.

Was ich normalerweise mache ist

%Vor%

Dies ist meiner Meinung nach der beste Weg, um Indizes zu verwenden, da die Verwendung eines vorzeichenlosen Typs für einen Index (oder die Größe eines Containers) ein logischer Fehler ist.

Vorzeichenlose Typen sollten nur verwendet werden, wenn Sie sich für die Bitdarstellung interessieren und wenn Sie das modulo- (2 ** n) Verhalten beim Überlauf verwenden. Die Verwendung vorzeichenloser Typen, nur weil ein Wert niemals negativ ist, ist ein Unsinn.

Ein typischer Fehler bei der Verwendung vorzeichenloser Typen für Größen oder Indizes ist zum Beispiel

%Vor%

Der obige Code ist UB, wenn das Punkt-Array leer ist, weil in C ++ 0u-1 mit eine riesige positive Zahl ist.

Der Grund, warum C ++ einen vorzeichenlosen Typ für die Größe von Containern verwendet, ist, dass diese Wahl ein historisches Erbe von 16-Bit Computern ist (und IMO C ++ Semantik mit unsignierten Typen gab es schon damals die falsche Wahl).

    
6502 02.11.2011 18:04
quelle
1

Normalerweise löse ich es so:

%Vor%

Ich benutze den C-Style-Cast, weil er kürzer und lesbarer als C ++ static_cast<int>() ist und dasselbe erreicht.

Es gibt hier ein Potenzial für einen Überlauf, aber nur, wenn Ihre Vektorgröße größer ist als die größte int , typischerweise 2147483647. Ich hatte noch nie in meinem Leben einen so großen Vektor. Wenn es sogar eine entfernte Möglichkeit gibt, einen größeren Vektor zu verwenden, wäre eine der Antworten, die size_type vorschlagen, geeigneter.

Ich mache mir keine Sorgen, dass size() wiederholt in der Schleife aufgerufen wird, da es wahrscheinlich ein Inline-Zugriff auf eine Membervariable ist, die keinen Overhead verursacht.

    
Mark Ransom 22.08.2016 15:47
quelle
0

Erklären 'size_t i' für mich gut funktionieren.

    
albert 06.07.2014 00:54
quelle

Tags und Links