Können Sie mir sagen, was genau das bewirkt u
nach einer Zahl, zum Beispiel:
#define NAME_DEFINE 1u
Lodhart
Können Sie mir sagen, was genau das bewirkt u
nach einer Zahl, zum Beispiel:
#define NAME_DEFINE 1u
Lundin
Ganzzahlige Literale wie 1
in C-Code sind immer vom Typ int
. int
ist dasselbe wie signed int
. Man fügt hinzu u
oder U
(äquivalent) zum Literal, um sicherzustellen, dass es unsigned int ist, um verschiedene unerwartete Fehler und seltsames Verhalten zu verhindern.
Ein Beispiel für einen solchen Fehler:
Auf einem 16-Bit-Rechner, auf dem int 16 Bit ist, führt dieser Ausdruck zu einem negativen Wert:
long x = 30000 + 30000;
Beide 30000-Literale sind int, und da beide Operanden int sind, ist das Ergebnis int. Ein 16-Bit-Int mit Vorzeichen kann nur Werte bis zu 32767 enthalten, sodass es überläuft. x
wird dadurch einen seltsamen, negativen Wert erhalten, anstatt wie erwartet 60000.
Der Code
long x = 30000u + 30000u;
wird sich jedoch wie erwartet verhalten.
this expression will result in a negative value
. Nun, oder Dämonen fliegen aus Ihrer Nase, da Integer-Überläufe undefiniertes Verhalten sind.
– au
27. Januar 2012 um 9:01 Uhr
@ouah Theoretisch ja. In der realen Welt behandeln alle Compiler, die ich je gesehen habe, ganzzahlige Überläufe auf die gleiche Weise. Wie auch immer, es ist ein Fehler, unabhängig vom Ergebnis.
– Ludin
27. Januar 2012 um 10:10 Uhr
Die Tatsache, dass ein ganzzahliger Überlauf undefiniert ist, ist nicht nur theoretisch. Selbst in der realen Welt nutzen Compiler den Überlauf von Ganzzahlen als undefiniertes Verhalten, um Optimierungen durchzuführen. gcc
hat zum Beispiel mindestens 20 Fälle, in denen es keinen Integer-Überlauf zum Umbrechen in Betracht zieht, damit es eine Optimierung durchführen kann. Ein einfaches Beispiel ist ein Ausdruck wie a - 8 < 42
wenn a
ist ein signierter Typ gcc
könnte den Ausdruck reduzieren auf a < 50
.
– au
27. Januar 2012 um 10:28 Uhr
Antwort auf den Kommentar von @ouah: unsigned overflow ist definiert, vorzeichenbehafteter Überlauf nicht. Siehe: diese SO-Frage
– svek
5. April 2017 um 19:59 Uhr
@svec in der C-Terminologie Ganzzahlüberlauf ist undefiniertes Verhalten, da nur vorzeichenbehaftete Ganzzahlen überlaufen können. Siehe C11, 3.4.3p3 „Ein Beispiel für undefiniertes Verhalten ist das Verhalten bei Ganzzahlüberlauf“ und 6.2.5p7 „Eine Berechnung mit vorzeichenlosen Operanden kann niemals überlaufen, […]”
– au
5. April 2017 um 21:19 Uhr
Es ist eine Art zu definieren ohne Vorzeichen wörtliche ganzzahlige Konstanten.
Es ist eine Möglichkeit, dem Compiler mitzuteilen, dass die Konstante 1 als Ganzzahl ohne Vorzeichen verwendet werden soll. Einige Compiler gehen davon aus, dass jede Zahl ohne Suffix wie ‘u’ vom Typ int ist. Um diese Verwirrung zu vermeiden, wird empfohlen, ein Suffix wie „u“ zu verwenden, wenn eine Konstante als Ganzzahl ohne Vorzeichen verwendet wird. Es gibt auch andere ähnliche Suffixe. Beispielsweise wird für Float ‘f’ verwendet.
Nicht “einige Compiler”. Alle Compiler.
– Ludin
27. Januar 2012 um 7:50 Uhr
Ich wollte nicht verallgemeinern, da ich persönlich nur ein paar Compiler verwendet habe.
– Mokka
27. Januar 2012 um 8:06 Uhr
Mein Punkt ist, dass der C-Standard den Compiler dazu zwingt, ein Integer-Literal ohne ‘u’ als signed int zu behandeln.
– Ludin
27. Januar 2012 um 8:45 Uhr
@Lundin Nicht ganz richtig, es kann auch lang oder lang lang sein. Ohne Suffix ist der Typ eines Integer-Literals der erste von int
, long
und long long
die den Wert halten kann (falls vorhanden).
– Daniel Fischer
27. Januar 2012 um 13:00 Uhr
@DanielFischer: Das stimmt. Aber es wird immer ein signierter Typ sein, es sei denn, Sie schreiben das ‘u’.
– Ludin
27. Januar 2012 um 15:16 Uhr
es bedeutet “unsigned int”, im Grunde funktioniert es wie ein Cast, um sicherzustellen, dass numerische Konstanten zur Kompilierzeit in den entsprechenden Typ konvertiert werden.
Dirk Herrmann
Ein dezimales Literal im Code (die Regeln für oktale und hexadezimale Literale sind unterschiedlich, siehe https://en.cppreference.com/w/c/language/integer_constant) hat einen der Typen int
, long
oder long long
. Aus diesen muss der Compiler den kleinsten Typ auswählen, der groß genug ist, um den Wert aufzunehmen. Beachten Sie, dass die Typen char
, signed char
und short
werden nicht berücksichtigt. Zum Beispiel:
0 // this is a zero of type int
32767 // type int
32768 // could be int or long: On systems with 16 bit integers
// the type will be long, because the value does not fit in an int there.
Wenn Sie ein hinzufügen u
Suffix für eine solche Zahl (ein Großbuchstabe U
geht auch), muss der Compiler stattdessen den kleinsten Typ auswählen unsigned int
, unsigned long
und unsigned long long
. Zum Beispiel:
0u // a zero of type unsigned int
32768u // type unsigned int: always fits into an unsigned int
100000u // unsigned int or unsigned long
Anhand des letzten Beispiels kann der Unterschied zu einem Guss aufgezeigt werden:
100000u // always 100000, but may be unsigned int or unsigned long
(unsigned int)100000 // always unsigned int, but not always 100000
// (e.g. if int has only 16 bit)
Nebenbei bemerkt: Es gibt Situationen, in denen das Hinzufügen von a u
Suffix ist das Richtige, um die Korrektheit der Berechnungen sicherzustellen, wie Lundins Antwort zeigt. Es gibt jedoch auch Codierungsrichtlinien, die das Mischen von signierten und unsignierten Typen strengstens verbieten, selbst soweit die folgende Aussage
unsigned int x = 0;
wird als nicht konform eingestuft und muss so geschrieben werden
unsigned int x = 0u;
Dies kann dazu führen, dass Entwickler, die sich viel mit vorzeichenlosen Werten beschäftigen, die Angewohnheit entwickeln, zu addieren u
Suffixe zu Literalen überall. Beachten Sie jedoch, dass eine Änderung der Signierung in verschiedenen Kontexten zu unterschiedlichem Verhalten führen kann, z. B.:
(x > 0)
kann (je nach Art von x) etwas anderes bedeuten als
(x > 0u)
Glücklicherweise warnt Sie der Compiler / Code-Checker normalerweise vor verdächtigen Fällen. Trotzdem fügt man a hinzu u
Suffix sollte mit Bedacht erfolgen.