Willkommen bei der Ganzzahl-Promotion . Wenn ich von der Website zitieren darf:
Wenn ein int alle Werte des ursprünglichen Typs darstellen kann, wird der Wert in einen int konvertiert. Andernfalls wird es in ein vorzeichenloses int konvertiert. Diese werden als Integer-Promotions bezeichnet. Alle anderen Typen bleiben durch die ganzzahligen Aktionen unverändert.
C kann sehr verwirrend sein, wenn Sie Vergleiche wie diese anstellen. Ich habe kürzlich einige meiner Nicht-C-Programmierfreunde mit folgendem Scherz verwirrt:
#include <stdio.h>
#include <string.h>
int main()
{
char* string = "One looooooooooong string";
printf("%d\n", strlen(string));
if (strlen(string) < -1) printf("This cannot be happening :(");
return 0;
}
Was tatsächlich druckt This cannot be happening :(
und anscheinend zeigt, dass 25 kleiner als -1 ist!
Was jedoch darunter passiert, ist, dass -1 als vorzeichenlose Ganzzahl dargestellt wird, die aufgrund der zugrunde liegenden Bitdarstellung auf einem 32-Bit-System gleich 4294967295 ist. Und natürlich ist 25 kleiner als 4294967295.
Wenn wir jedoch den von zurückgegebenen size_t
Typ explizit strlen
als vorzeichenbehaftete Ganzzahl umwandeln:
if ((int)(strlen(string)) < -1)
Dann wird es 25 gegen -1 vergleichen und alles wird gut mit der Welt.
Ein guter Compiler sollte Sie vor dem Vergleich zwischen einer vorzeichenlosen und einer vorzeichenbehafteten Ganzzahl warnen, und dennoch ist es so leicht zu übersehen (insbesondere, wenn Sie keine Warnungen aktivieren).
Dies ist besonders verwirrend für Java-Programmierer, da alle primitiven Typen dort signiert sind. Hier ist, was James Gosling (einer der Schöpfer von Java) zu diesem Thema zu sagen hatte :
Gosling: Für mich als Sprachdesigner, den ich heutzutage nicht wirklich als solche bezeichne, bedeutete "einfach" letztendlich, dass ich erwarten konnte, dass J. Random Developer die Spezifikation in seinem Kopf hält. Diese Definition besagt, dass Java zum Beispiel nicht Java ist - und tatsächlich enden viele dieser Sprachen mit vielen Eckfällen, Dinge, die niemand wirklich versteht. Fragen Sie jeden C-Entwickler nach unsigned, und schon bald stellen Sie fest, dass fast kein C-Entwickler wirklich versteht, was mit unsigned vor sich geht, was unsigned-Arithmetik ist. Solche Dinge machten C komplex. Der sprachliche Teil von Java ist meiner Meinung nach ziemlich einfach. Die Bibliotheken müssen Sie nachschlagen.