2010-08-14 8 views
23

Normalerweise erfordert C, dass Operanden eines binären Operators zum Typ des übergeordneten Operanden hochgestuft werden. Dies kann zu vermeiden, ausgenutzt werden Code mit ausführlichen Abgüsse Füllung, zum Beispiel:Bitshift und Integer-Promotion?

if (x-48U<10) ... 
y = x+0ULL << 40; 

usw.

Allerdings habe ich festgestellt, dass, zumindest mit gcc, tritt dieses Verhalten nicht für bitshifts arbeiten. I.e.

int x = 1; 
unsigned long long y = x << 32ULL; 

Ich würde den Typ des rechten Operanden erwartet, dass die linken Operanden bewirken unsigned long long gefördert werden, so dass die Verschiebung erfolgreich ist. Aber stattdessen gcc druckt eine Warnung:

warning: left shift count >= width of type 

gcc gebrochen ist, oder hat der Standard eine Ausnahme von der Typ Förderung Regeln für bitshifts machen?

+0

Wird es trotzdem fördern, unabhängig von der Warnung? (Es ist nur eine Warnung, immerhin). –

+1

Könnten Sie nicht einfach ein kurzes Makro verwenden, um die ausführliche Besetzung zu erstellen? Wie '#definiere ULL (x) ((unsigned long long) x)'? – Borealid

+1

@Robert: Nein, es erzeugt ein No-Op, als ob ich einfach '<< 32 geschrieben hätte. @ Borealid: Ja, ich könnte, aber ich schreibe gern Code, der überall kopiert und eingefügt werden kann (z. B. andere Projekte), ohne dass zusätzliche Definitionen/Header erforderlich sind. Ich hasse Dinge wie 'typedef unsigned int uint;'. –

Antwort

23

Die sogenannten üblichen arithmetischen Umwandlungen gelten für viele binäre Operatoren, aber nicht alle von ihnen. Zum Beispiel gelten sie nicht für die Bit-Shift-Operatoren & &, ||, Kommaoperator und Zuweisungsoperatoren. Das ist die Regel für die Bit-Shift-Operatoren:

6.5.7 ... 3 Semantics ...
Die Integer-Aktionen sind auf jedem des Operanden durchgeführt. Der Typ des Ergebnisses ist der des hochgestuften linken Operanden. Wenn der Wert des rechten Operanden negativ ist oder größer oder gleich der Breite des aktualisierten linken Operanden ist, ist das Verhalten nicht definiert.

+1

Danke, das ist, was ich gesucht habe. –

0

Das Problem ist wirklich, dass Promotion nur funktioniert, was auch immer Ihre Plattform als int definiert. Wie einige andere Antworten angegeben haben, wird der Bit-Shift-Operator den linken Operanden zu einem int hochstufen. Hier ist jedoch ein int als ein 32-Bit-Wert definiert. Die ganzzahlige Konvertierung wird nicht zu einem long long (64-Bit) heraufstufen.