webentwicklung-frage-antwort-db.com.de

Vorzeichenlose Werte in C

Ich habe folgenden Code:

#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;
}

Die Ausgabe ist:

ffffffff
ffffffff
-1
-1
4294967295
4294967295

Ich kann sehen, dass ein Wert entsprechend dem an printf übergebenen Wert als vorzeichenbehaftet oder vorzeichenlos interpretiert wird. In beiden Fällen sind die Bytes gleich (ffffffff). Was ist dann das unsigned Word?

15
rvillablanca

Weisen Sie einer unsigned einen int -1 zu: Da -1 nicht in den Bereich [0...UINT_MAX] passt, werden Vielfache von UINT_MAX+1 hinzugefügt, bis sich die Antwort in Reichweite befindet. Offensichtlich ist UINT_MAXpow(2,32)-1 or 429496725 auf der OP-Maschine, also hat a den Wert 4294967295.

    unsigned int a = -1;

Der "%x", "%u"-Bezeichner erwartet eine übereinstimmende unsigned. Da diese nicht übereinstimmen, "Wenn eine Konvertierungsspezifikation ungültig ist, ist das Verhalten undefined. Wenn ein Argument nicht der richtige Typ für die entsprechende Konvertierungsspezifikation ist, ist das Verhalten undefined." C11 §7.21.6.1 9. Der printf-Bezeichner ändert b nicht.

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

Der "%d"-Bezeichner erwartet eine übereinstimmende int. Da diese nicht übereinstimmen, ist mehr UB.

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

Bei undefiniertem Verhalten werden die Schlussfolgerungen nicht unterstützt.


in beiden Fällen sind die Bytes gleich (ffffffff).

Selbst bei demselben Bitmuster können verschiedene Typen unterschiedliche Werte haben. ffffffff als unsigned hat den Wert 4294967295. Als int, je nach vorzeichenbehafteter Ganzzahlkodierung, hat sie den Wert -1, -2147483647 oder TBD. Als float kann es sich um ein NAN handeln.

wofür ist unsigniertes Word?

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: Um eine Compiler-Warnung zum Zuweisen einer signierten int zu unsigned zu vermeiden, verwenden Sie das Folgende. Dies ist eine unsigned1u, die negiert wird - was wie oben definiert ist. Der Effekt ist derselbe wie ein -1, vermittelt jedoch dem Compiler direkte Absichten.

unsigned int a = -1u;
12
chux

Die Variablendeklaration von unsigned ist für die Programmierer selbst sinnvoller - 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 wollen.

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

0
Donotalo

Wenn Sie unsigned int a to -1; initialisieren, bedeutet dies, dass Sie das 2's -Komplement von -1 im Speicher von a speichern.
Das ist nichts anderes als 0xffffffff oder 4294967295.

Wenn Sie also mit dem %x or %u-Formatbezeichner drucken, erhalten Sie diese Ausgabe. 

Durch Festlegen der Signiertheit einer Variablen, um die minimale und maximale Wertgrenze festzulegen, 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 zum Signedness siehe this

0
Santosh A