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:
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.
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).
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.
Beantworten nach so vielen Antworten, aber niemand bemerkte das Ende der Schleife .. Also, hier ist meine vollständige Antwort:
i
in unsigned
, auto
(für C ++ 11) oder std::vector< your_type >::size_type
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 )
<
, 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 :) ). 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).
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.
Tags und Links c++