2015-09-02 3 views
8

Ich habe den folgenden Code:Unsigniert Werte in C

#include <stdio.h> 

int main() { 
    unsigned int a = -1; 
    int b = -1; 
    printf("%x\n", a); 
    printf("%x\n", b); 

    printf("%d\n", a); 
    printf("%d\n", b); 

    printf("%u\n", a); 
    printf("%u\n", b); 
    return 0; 
} 

Der Ausgang ist:

ffffffff 
ffffffff 
-1 
-1 
4294967295 
4294967295 

I kann sehen, dass ein Wert, der mit oder ohne Vorzeichen interpretiert wird entsprechend dem Wert übergeben printf Funktion. In beiden Fällen sind die Bytes gleich (ffffffff). Dann, was ist das unsigned Wort für?

+0

Siehe auch: [** Zwei-Komplement - Wikipedia, die freie Enzyklopädie **] (https://en.wikipedia.org/wiki/Two%27s_complement) Die kurze Antwort „, wenn das höchstwertige Bit ist '1', wird es als ** negative ** Ganzzahl interpretiert." –

+0

http://www.cplusplus.com/forum/startner/94567/ –

+0

Ja, aber das wird mit der 'printf' Funktion gemacht, dann kann ich nicht verstehen, welche Rolle das' unsigned' Wort spielt. In meinem Beispiel könnte ich sowohl für signierte als auch für nicht signierte vars den Wert als signed oder unsigned sehen. Um zu verdeutlichen, wenn ich eine signierte var als signed oder unsigned gedruckt sehen kann, was ist "unsigned" Wort für? – rvillablanca

Antwort

5

Weisen ein int -1 zu einem unsigned: Wie -1 nicht passt Der Bereich [0...UINT_MAX], Vielfache von werden hinzugefügt, bis die Antwort in Reichweite ist.Offensichtlich UINT_MAX ist pow(2,32)-1 or 429496725 auf OP-Maschine so a hat den Wert von .

unsigned int a = -1; 

Die "%x" erwartet "%u" Spezifizierer ein passender unsigned. Da diese nicht übereinstimmen: "Wenn eine Konvertierungsspezifikation ungültig ist, ist das Verhalten nicht definiert. Wenn ein Argument nicht der richtige Typ für die entsprechende Konvertierungsspezifikation ist, ist das Verhalten nicht definiert." C11 §7.21.6.1 9. Der printf specifier ändert nicht b.

printf("%x\n", b); // UB 
    printf("%u\n", b); // UB 

Der "%d" Spezifizierer erwartet eine passende int. Da diese nicht übereinstimmen, mehr UB.

printf("%d\n", a); // UB 

Bei nicht definiertem Verhalten werden die Schlussfolgerungen nicht unterstützt.


beiden Fällen werden die Bytes gleich ist (FFFFFFFF).

Auch bei gleichem Bitmuster können unterschiedliche Typen unterschiedliche Werte haben. ffffffff als unsigned hat den Wert 4294967295. Als int, abhängige Ganzzahlkodierung mit Vorzeichen, hat es den Wert -1, -2147483647 oder TBD. Als float kann es ein NAN sein.

was ist ein nicht vorzeichenbehaftetes Wort?

unsigned speichert eine ganze Zahl im Bereich [0 ... UINT_MAX]. Es hat nie einen negativen Wert. Wenn der Code eine nicht negative Zahl benötigt, verwenden Sie unsigned. Wenn der Code eine Zählnummer benötigt, die +, - oder 0 sein kann, verwenden Sie int.


Update: einen Compiler Warnung über die Zuweisung einer unterzeichneten int zu unsigned, verwenden Sie die unten zu vermeiden. Dies ist eine unsigned1u wird negiert - was gut wie oben definiert ist. Der Effekt ist der gleiche wie ein -1, vermittelt aber dem Compiler direkte Absichten.

unsigned int a = -1u; 
+0

Ihre Aussage über UB ist falsch. Bitte lesen Sie die Absätze über der zitierten Stelle noch einmal. TL; DR: Jeder Konvertierungsspezifizierer, der der Grammatik folgt, ist "gültig". Mit anderen Worten, in 'printf ("% d", "foo") ist der Spezifizierer "% d" gültig, in dem Sinne, dass sich der zitierte Absatz bezieht. Natürlich versuchen Sie, einen String als int zu drucken, aber nicht aus dem Grund, den Sie zu denken scheinen. Eher "die richtige Typ-Promotion oder -Konvertierung wird durchgeführt, wenn erlaubt" und da keine Typ-Heraufstufung oder -Konvertierung von String zu Int erlaubt ist, wird es UB. – AnorZaken

+0

@AnorZaken Antwort geändert, um zu betonen, dass der printf-Spezifizierer und der Argumenttyp nicht übereinstimmen. – chux

-5

In der hexadezimalen kann es keinen negativen Wert erhalten. So zeigt es sich wie ffffffff.

Der Vorteil der unsignierte Version zu verwenden (wenn Sie die Werte wissen nicht negativ sein enthalten ist) ist, dass manchmal die Computer-Fehler für Sie vor Ort wird (das Programm „Absturz“, wenn ein negativer Wert ist der Variablen zugewiesen).

+2

Zuweisen eines negativen Werts zu einer "unsigned" Variable hat wohldefiniertes Verhalten. –

+1

'unsigned i = -1;' führt immer dazu, dass der INT_MAX-Wert i zugewiesen wird. Kein Absturz hier –

0

unsigned in Variablendeklaration ist für die Programmierer selbst nützlicher - behandeln Sie die Variablen nicht als negativ. Wie Sie bemerkt haben, haben sowohl -1 als auch 4294967295 genau dieselbe Bitdarstellung für eine 4-Byte-Ganzzahl. Es geht darum, wie Sie behandeln oder sehen ihnen.

Die Anweisung unsigned int a = -1; konvertiert -1 in Zweierkomplement und weist die Bitdarstellung in a zu. Die printf() Spezifizierer x, d und u zeigen, wie die in der Variablen a gespeicherte Bitdarstellung in einem anderen Format aussieht.

0

Wenn Sie unsigned int a to -1; initialisieren bedeutet es, dass Sie die 2's Komplement -1 in den Speicher des a werden zu speichern.
Welches ist nichts als 0xffffffff oder 4294967295.

Daher, wenn Sie es mit %x or %u Format-Spezifizierer drucken, erhalten Sie diese Ausgabe.

Durch Angabe der Signedness einer Variablen zur Festlegung der minimalen und maximalen Wertgrenze, die gespeichert werden kann.

Wie bei unsigned int: Der Bereich ist von 0 to 4,294,967,295 und int: Der Bereich ist von -2,147,483,648 to 2,147,483,647

Für weitere Informationen über Signedness siehe this