Signierte ganzzahlige Variablen haben kein Wrack-Verhalten in der C-Sprache. Der signierte Ganzzahlüberlauf während arithmetischer Berechnungen erzeugt undefiniertes Verhalten. Beachten Sie übrigens, dass der von Ihnen erwähnte GCC -Compiler für die Implementierung bekannt ist Strenge Überlaufsemantik In Optimierungen nutzt es die Freiheit, die solche undefinierten Verhaltenssituationen bereitzustellen: GCC -Compiler geht davon aus, dass signierte ganzzahlige Werte nie umwickeln. Das bedeutet, dass GCC tatsächlich einer der Compiler ist, in denen Sie kann nicht Verlassen Sie sich auf ein Wrack-Verhalten von signierten Ganzzahltypen.
Zum Beispiel kann der GCC -Compiler dies für eine Variable annehmen int i
die folgende Bedingung
if (i > 0 && i + 1 > 0)
entspricht nur einem bloßen
if (i > 0)
Genau das ist was Strenge Überlaufsemantik meint.
Unsignierte ganzzahlige Typen implementieren Modulo -Arithmetik. Das Modulo ist gleich 2^N
wo N
ist die Anzahl der Bits in der Wertdarstellung des Typs. Aus diesem Grund scheinen unsignierte ganzzahlige Typen tatsächlich mit dem Überlauf umzugehen.
Die C -Sprache führt jedoch niemals arithmetische Berechnungen in Domänen durch, die kleiner sind als die von int
/unsigned int
. Typ unsigned short int
Das Sie in Ihrer Frage erwähnen, wird normalerweise zum Typ -Typ befördert int
in Ausdrücken vor Beginn aller Berechnungen (vorausgesetzt, der Bereich von unsigned short
passt in den Bereich von int
). Was bedeutet, dass 1) die Berechnungen mit unsigned short int
wird in der Domäne von vorgeformt int
, mit Überlauf, wenn int
Überläufe, 2) Überlauf während solcher Berechnungen führt zu undefiniertem Verhalten, nicht zu einem Verhalten von Wickeln.
Zum Beispiel erzeugt dieser Code eine Umwicklung
unsigned i = USHRT_MAX;
i *= INT_MAX; /* <- unsigned arithmetic, overflows, wraps around */
während dieser Code
unsigned short i = USHRT_MAX;
i *= INT_MAX; /* <- signed arithmetic, overflows, produces undefined behavior */
führt zu undefiniertem Verhalten.
Wenn nein int
Überlauf tritt auf und das Ergebnis wird wieder auf eine konvertiert unsigned short int
Typ, es wird erneut durch Modulo reduziert 2^N
, was so aussieht, als ob sich der Wert umwickelt hat.