2015-05-18 10 views
5

Arbeiten auf diesem kleinen Stück Code in VS2013, aber aus irgendeinem Grund scheint es nicht print.it dass -1> strlen (str)Warum ist -1> strlen (t) in C wahr?

Jeder bekam eine Idee, was ich falsch mache

char *str="abcd"; 
if(-1<strlen(str)) 
printf("The size of the string is %d", strlen(str));  
return 0; 
+1

Was ist der Ausgabewert von 'strlen (str)'? – sasquatch

+1

Könnte sein, dass es unsigned Wert zurückgibt und das Dinge bricht –

+2

es ist gut, Warnungen zu maximalen Einstellungen auf Ihrem Compiler zu aktivieren –

Antwort

10

Jeder bekam eine Idee, was ich falsch mache

strlen() gibt einen size_t, die einen nicht signierten Integer-Typ ist. -1 interpretiert als eine vorzeichenlose Ganzzahl ist ein großer Wert, so dass es größer als die Länge der Zeichenfolge ist. Sie können das Flag -Wsign-compare in gcc und einige andere Compiler verwenden, um Sie zu warnen, wenn Sie versuchen, signierte und unsignierte Werte zu vergleichen.

Auch macht es wenig Sinn, die Länge einer Zeichenkette mit -1 zu vergleichen. Eine Länge kann niemals negativ sein; es ist immer gehen 0 oder größer sein. Sie werden also wahrscheinlich Ihren Code neu schreiben müssen, um ihn gegen 0 zu testen, oder Sie können die Bedingungen, die Sie testen möchten, auf andere Weise korrekt implementieren.

if(-1<strlen(str)) printf("The size of the string is %d", strlen(str));

In diesem Code kann man vernünftigerweise den Test immer erwarten, dass um erfolgreich zu sein und die printf() auszuführen, da die Länge immer 0 oder mehr ist. Aber Sie finden, dass der Test tatsächlich fehlschlägt und die printf() nie passiert, weil -1 zu einem unsigned heraufgestuft wird, so dass es mit einem size_t verglichen werden kann. Die einfache Lösung ist, den Zustand vollständig zu entfernen: Sie wissen, dass der Test immer erfolgreich sein wird, also ist es nicht nötig. Entfernen Sie einfach die if*:

printf("The size of the string is %zu", strlen(str)); 

* Auch das Spezifikationsdruckformat von %d zu %zu da ändern, wie Matt McNabb in einem Kommentar darauf hingewiesen, sie ist ein size_t Versuch zu drucken.

+1

Sie könnten das OP über Compiler-Warnungen informieren, die, falls aktiviert, diese Art von Fehlern verhindern. – chqrlie

+0

@chqrlie Guter Vorschlag; erledigt. – Caleb

+1

Vielen Dank! –

4

strlen(str) gibt eine vorzeichenlose Ganzzahl zurück. Beim Vergleich von vorzeichenbehafteten Ganzzahlen mit vorzeichenlosen Ganzzahlen konvertiert der Compiler den vorzeichenbehafteten Wert in vorzeichenlos. Bei Umwandlung in vorzeichenlos wird -1 zu 2^32 - 1 (vorausgesetzt, dass strlen eine 32-Bit-Ganzzahl zurückgibt), die größer ist als die Länge der Zeichenfolge, mit der Sie vergleichen.

+1

Gehen Sie nicht davon aus, dass "size_t" 32 Bits lang ist. – Caleb

+0

Sie könnten das OP über Compiler-Warnungen informieren, die, falls aktiviert, diese Art von Fehlern verhindern. – chqrlie

+0

Die Konvertierung erfolgt nach 'size_t', nicht nach' int'. 'strlen' gibt' size_t' zurück und es ist heutzutage üblich, dass es mehr als 32 Bits ist. – juanchopanza

4

strlen gibt einen Wert vom Typ size_t zurück. Dies ist ein vorzeichenloser ganzzahliger Typ.

Die Regel in C für den Vergleich eines vorzeichenbehafteten Werts mit einem Wert des entsprechenden vorzeichenlosen Typs besteht darin, dass der vorzeichenbehaftete Wert in den vorzeichenlosen Wert konvertiert wird.

Wenn die Werte unterschiedlich groß sind, z. B. wenn Ihr System über 4 Byte int und 8 Byte size_t verfügt, wird der Wert des kleineren Typs in den Wert des größeren Typs konvertiert.

In beiden Fällen bedeutet dies, dass -1 in size_t konvertiert wird, was zu SIZE_MAX führt, was einen großen positiven Wert darstellt. (vorzeichenlose Typen können keine negativen Werte enthalten).

Dieser große positive Wert ist größer als die Länge der Zeichenfolge, daher gibt der Kleiner-als-Vergleich den Wert false zurück.

+0

Sie könnten das OP über Compiler-Warnungen informieren, die, falls aktiviert, diese Art von Fehlern verhindern. – chqrlie

+0

@chqrlie hängt von der Qualität des Compilers und den Einstellungen ab. Ich tendiere dazu, signierte-unsignierte Warnungen zu deaktivieren, da diese häufiger falsch sind. –

+0

Vielen Dank! –