Warum passiert das mit der Größe des Operators beim Vergleich mit einer negativen Zahl?

Was passiert hier wirklich? Die Ausgabe ist jetzt “False”:

#include  int main() { if (sizeof(int) > any_negative_integer) printf("True"); else printf("False"); return 0; } 

Wenn ich es ändere zu:

 if (sizeof(int) < any_negative_integer) 

Die Ausgabe ist “True”.

Update: die gleiche Frage wurde bereits gestellt, ich konnte es nicht finden bevor ich frage.

   

sizeof gibt size_t das ist unsigned und so wird -1 in eine sehr große vorzeichenlose Zahl konvertiert. Die Verwendung der richtigen Warnstufe hätte hier geholfen, -Wconversion mit den -Wconversion oder -Weverything ( beachten Sie, dass dies nicht für die Produktion verwendet wird ) warnt uns:

 warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion] if (sizeof(int) > -1) ~ ^~ 

Für gcc erhalten Sie eine ähnliche Warnung mit dem -Wextra Flag:

 warning: comparison between signed and unsigned integer expressions [-Wsign-compare] if (sizeof(int) > -1) ^ 

Als Referenz wissen wir, dass size_t aus dem Entwurf C99-Standardabschnitt 7.17 Gemeinsame Definitionen, die sagen:

  size_t 

was ist der vorzeichenlose Integer-Typ des Ergebnisses des Operators sizeof; […]

Beachten Sie, dass es nichts anderes über den Typ angibt, in meinem speziellen Fall ist es lange nicht signiert, aber es muss nicht sein.

Die Umwandlung von -1 ist auf die übliche arithmetische Umwandlung zurückzuführen, die in Abschnitt 6.3.1.8 Übliche arithmetische Konvertierungen behandelt wird, die besagt:

[…]

Andernfalls, wenn der Operand, der einen vorzeichenlosen Integer-Typ aufweist, einen Rang hat, der größer oder gleich dem Rang des Typs des anderen Operanden ist, dann wird der Operand mit vorzeichenbehafteten Integer-Typ in den Typ des Operanden mit vorzeichenlosen Integer-Typ konvertiert.

Wenn der Typ des Operanden mit vorzeichenbehafteten Integer-Typ andernfalls alle Werte des Typs des Operanden mit vorzeichenlosen Integer-Typen darstellen kann, wird der Operand mit vorzeichenloser Ganzzahl in den Typ des Operanden mit Ganzzahl mit Vorzeichen konvertiert.

Andernfalls werden beide Operanden in den vorzeichenlosen ganzzahligen Typ konvertiert, der dem Typ des Operanden mit vorzeichenbehafteten Integer-Typen entspricht.

Also würde die einzige Zeit -1 nicht in einen vorzeichenlosen Wert konvertiert werden, wenn int alle Werte von size_t repräsentieren könnte, was hier nicht der Fall ist.

Warum -1 am Ende ein großer vorzeichenloser Wert ist, ist es eigentlich der Maximalwert des vorzeichenlosen Typs aufgrund von Abschnitt 6.3.1.3 Signed und unsigned Ganzzahlen, die sagen:

Wenn der neue Typ nicht vorzeichenbehaftet ist, wird der Wert andernfalls durch wiederholtes Hinzufügen oder Subtrahieren von mehr als dem Maximalwert, der im neuen Typ dargestellt werden kann, konvertiert, bis der Wert im Bereich des neuen Typs liegt. 49)

Also enden wir mit:

 -1 + (UMAX + 1) 

welches ist:

 UMAX 

und damit enden mit:

 if (sizeof(int) > UMAX ) 

Weil sizeof() einen size_t zurückgibt, einen vorzeichenlosen Typ. Der Vergleich signierter und vorzeichenloser Typen kann aufgrund des impliziten Castings vor dem Vergleich zu überraschenden Ergebnissen führen.