2010-02-28 7 views
12

Ich habe folgende Array, die ich auf Bitmaps von Hand bedienen muss.C++: Compiler Warnung für große unsigned int

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
           2048, 4096, 8192, 16384, 32768, 65536, 131072, 
           262144, 524288, 1048576, 2097152, 4194304, 
           8388608, 16777216, 33554432, 67108864, 134217728, 
           268435456, 536870912, 1073741824, 2147483648}; 

Leider kompiliert, wenn ich

Warnung: Diese Dezimalkonstante unsigned ist nur in ISO C90

Wie kann ich diese entfernen?

+0

diese ähnliche Frage Siehe: http://stackoverflow.com/questions/2347936/cant-get-ride-of-this-decimal-constant -is-unsigned-only-in-iso-c90-Warnung –

+0

Warum machst du das? Wenn Sie denken, dass eine Nachschlagetabelle schneller sein wird, als einfach diese Werte nach Bedarf zu berechnen, denken Sie noch einmal darüber nach ... – Nemo

Antwort

15

Integer Literale in C sind standardmäßig vom Typ "signed int" (edit: aber siehe Kommentare für Vorbehalte). Die letzte Zahl ist zu groß als 32-Bit-Ganzzahl dargestellt zu werden, und so müssen Sie den Compiler sagen, dass es eine ganze Zahl ohne Vorzeichen indem sie sie mit „U“ suffixing, wie:

2147483648U 

Beachten Sie, dass Sie können auch ein Suffix von "L" hinzufügen, um es zu "lang" zu machen, aber auf vielen Systemen ist das immer noch 32-Bit und damit irrelevant.

Auch gibt es einen viel weniger fehleranfällig (und leichter zu lesen) Weg, um diesen Code zu schreiben, mit dem Bit-Shift-Operator:

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4, 
           /* and so on */ 
           1U<<31}; 

Oder in hexadezimalen schreiben, wenn Sie don aus irgendeinem Grund wie Bit-Verschiebungen:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 
           /* and so on */ 
           0x80000000U}; 
+0

Warum behandelt der Compiler es dann als int, anstatt es automatisch in uint umzuwandeln? Insbesondere, dass es genau weiß, in welcher Art es gespeichert wird. – gruszczy

+0

In vielen Fällen können Sie nicht wissen, um welchen Typ es sich bei einer Konstante handelt (zum Beispiel als Funktionsargument in einer varargs-Funktion), daher muss sie explizit angegeben werden. Es ist verwirrend, dass der Typ mehrmals impliziert wird und in anderen explizit angegeben werden muss. Außerdem ist es verwirrend, wenn die gleiche Konstante auf Systemen mit unterschiedlichen int-Größen unterschiedliche Typen hat. Da C niemals eine derartige Inferenz eingibt, würde das Hinzufügen für diesen einen Fall den Parser ziemlich kompliziert machen, ohne dass ein signifikanter Nutzen daraus resultiert. –

+3

@gruszczy: In C89/90 muss eine unsuffixierte Dezimalkonstante als "int", "long" oder "unsigned long" interpretiert werden (je nachdem, was zuerst passt). In C99 muss es als "int", "long" oder "long long" interpretiert werden (was auch immer zuerst passt). Dies versucht der Compiler durch diese Warnung zu sagen. Anscheinend hat "long" auf dieser Plattform die gleiche Größe wie "int". Der Compiler sagt im Grunde: "Vielleicht hast du versucht eine' signed long' Konstante oder vielleicht eine 'long long' Konstante zu erzeugen, aber nach den C89/90 Regeln muss ich es 'unsigned long' machen. – AnT

6

Ihre Konstante hat als unsigned auch angegeben werden, verwenden

2147483648UL 

(UL = Unsigned Long) oder einfach

2147483648U 

für einen unsigned int.

Da Ihr Code gerade jetzt ist, wird eine Konstante, die standardmäßig eine Ebene int ist und daher signiert, einer unsigned int zugewiesen, die Ihre Warnung generiert.

+0

Das hat funktioniert, vielen Dank :-) – gruszczy

+3

Pedandisch gesprochen ist der Fehler nicht das, was von der Tatsache herrührt int) constant wird einem unsigned int zugewiesen; die Zuordnung ist irrelevant. Der Fehler liegt darin, dass der Wert von "2147483648" zu groß ist, um ein int-Zeichen zu sein, und daher gibt es einen Überlauf beim Generieren der vorzeichenbehafteten int-Konstante an erster Stelle. –

+2

Eigentlich ist der wirkliche Grund für die Warnung, dass der Compiler für den konstanten Typ "unsigned long" wählen muss. (Bitte beachten Sie, dass diese Konstante nicht 'unsigned int' ist, sondern 'unsigned long'). Sie muss sie in C89/90 auswählen, anstatt einen größeren signierten Typ zu wählen (was sie unterstützen könnte) oder nach C99 Regeln und wählen "lang lang". Darum geht es in der Warnung und warum es sich auf "ISO C90" bezieht. In C99 zum Beispiel würde eine unsuffixierte Dezimalkonstante niemals einen vorzeichenlosen Typ bekommen. – AnT

1

Nicht erforderlich, Datentyp als unsigned nur Typ zu definieren;

int variable_name=2147483648U; 

sonst umbauen Dezimalwert verhexen ...