2014-11-18 10 views
5

Nachdem ich die Frage 32 bit unsigned multiply on 64 bit causing undefined behavior? hier auf StackOverflow gelesen hatte, begann ich darüber nachzudenken, ob typische arithmetische Operationen an kleinen vorzeichenlosen Typen zu undefiniertem Verhalten gemäß dem C99-Standard führen könnten.Kann vorzeichenlose Ganzzahlinkrementierung zu undefiniertem definiertem Verhalten führen?

Nehmen wir zum Beispiel den folgenden Code:

#include <limits.h> 

... 

unsigned char x = UCHAR_MAX; 
unsigned char y = x + 1; 

Die x Variable auf die maximale Größe für den Datentyp unsigned char initialisiert wird. Die nächste Zeile ist das Problem: Der Wert x + 1 ist größer als UCHAR_MAX und kann nicht in der unsigned char Variablen y gespeichert werden.

Ich glaube, das Folgende ist was tatsächlich vorkommt.

  • Die Variable x ersten Datentyp int (Abschnitt 6.3.1.1/2) gefördert wird, wird dann als Datentyp x + 1int ausgewertet.

Angenommen, es ist eine Implementierung, wo INT_MAX und UCHAR_MAX gleich sind - x + 1 in einer signierten Integer-Überlauf führen würde. Bedeutet dies, dass das Inkrementieren der Variablen x trotz eines vorzeichenlosen Integer-Typs zu einem undefinierten Verhalten aufgrund eines möglichen vorzeichenbehafteten Integer-Überlaufs führen kann?

+0

Wenn 'sizeof (unsigned char) == sizeof (int)', gilt das erste Szenario. – chux

+1

@chux Warum würde eine Promotion nicht stattfinden, wenn ein 'int' den Wert darstellen kann? –

+0

Ich überprüfe "6.3.1.8 Übliche arithmetische Konvertierungen" Dies scheint zuerst zu gelten "Andernfalls, wenn der Operand, der vorzeichenlosen Integer-Typ hat Rang größer oder gleich dem Rang des Typs des anderen Operanden, dann der Operand mit signierten Integer-Typ wird in den Typ des Operanden mit unsigned Integer-Typ konvertiert. " Das kommt vor dem "Sonst, wenn der Typ des Operanden mit vorzeichenbehafteten Integer-Typ alle Werte des Typs des Operanden mit unsigned integer type ..." -Regel repräsentieren kann. – chux

Antwort

5

Durch meine Lektüre der Norm, eine Implementierung, die eine 15-Bit-char verwendet gesetzlich int als 15-Bit-Grße speichern kann und ein zweites 15-Bit-Wort verwenden, um die Zeichen zu speichern, zusammen mit 14 Bits padding; in diesem Fall würde ein unsigned char Werte von 0 bis 32.767 halten und ein int würde Werte von -32.767 bis +32.767 enthalten. Hinzufügen von 1 zu (unsigned char)32767 wäre in der Tat undefiniertes Verhalten. Eine ähnliche Situation könnte mit einer größeren Größe auftreten, wenn 32.767 durch UCHAR_MAX ersetzt wird.

Eine solche Situation ist jedoch unwahrscheinlich, verglichen mit den realen Problemen, die mit der Multiplikation von vorzeichenlosen Ganzzahlen verbunden sind, auf die in dem anderen Beitrag angespielt wird.