Was ist der Unterschied zwischen vorzeichenbehafteten und vorzeichenlosen int

89

Was ist der Unterschied zwischen signiertem und nicht signiertem int?

Moumita Das
quelle
5
Dies ist eine echte Frage, und die Antwort ist nicht so einfach, sondern eher subtil.
R .. GitHub STOP HELPING ICE
Abstimmung zur Wiedereröffnung. Es mag ein Duplikat sein, aber es ist definitiv eine echte Frage.
Brian
Weitere Tags sollten hinzugefügt werden, da sie von vielen Sprachen verwendet werden.
Juan Boero
Für diese Frage ist möglicherweise ein Kapitel erforderlich. Wenn Sie die Vor- und Nachteile kennen möchten, überprüfen Sie unsigned and Signed Integers, um weitere Erklärungen zu erhalten.
anonym

Antworten:

112

Wie Sie wahrscheinlich wissen, werden ints intern binär gespeichert. Normalerweise intenthält a 32 Bit, in einigen Umgebungen jedoch 16 oder 64 Bit (oder sogar eine andere Zahl, normalerweise, aber nicht unbedingt eine Zweierpotenz).

Schauen wir uns für dieses Beispiel 4-Bit-Ganzzahlen an. Winzig, aber nützlich zur Veranschaulichung.

Da eine solche Ganzzahl vier Bits enthält, kann sie einen von 16 Werten annehmen. 16 ist zwei nach der vierten Potenz oder 2 mal 2 mal 2 mal 2. Was sind diese Werte? Die Antwort hängt davon ab, ob diese Ganzzahl a signed intoder an ist unsigned int. Mit a unsigned intist der Wert niemals negativ; Dem Wert ist kein Vorzeichen zugeordnet. Hier sind die 16 möglichen Werte eines Vier-Bit unsigned int:

bits  value
0000    0
0001    1
0010    2
0011    3
0100    4
0101    5
0110    6
0111    7
1000    8
1001    9
1010   10
1011   11
1100   12
1101   13
1110   14
1111   15

... und hier sind die 16 möglichen Werte eines Vier-Bit signed int:

bits  value
0000    0
0001    1
0010    2
0011    3
0100    4
0101    5
0110    6
0111    7
1000   -8
1001   -7
1010   -6
1011   -5
1100   -4
1101   -3
1110   -2
1111   -1

Wie Sie sehen können, ist für signed ints das höchstwertige Bit 1genau dann, wenn die Zahl negativ ist. Deshalb ist signed intdieses Bit für s als "Vorzeichenbit" bekannt.

Bill Evans bei Mariposa
quelle
11
Hervorzuheben ist vielleicht, dass dies das Komplementformat der beiden ist, das heutzutage zugegebenermaßen weit verbreitet ist. Es gibt auch andere Möglichkeiten, vorzeichenbehaftete Ganzzahlen darzustellen, insbesondere die eigene Ergänzung.
Schedler
Richtig. Und die Norm ISO9899 C verlangt nicht einmal, dass entweder das eine oder das zweite Komplement verwendet wird. Jede andere Konvention, die tatsächlich funktioniert, ist zulässig.
Bill Evans bei Mariposa
1
Obwohl das Zweierkomplement nicht erforderlich (unsigned)(-1)ist, muss es der maximal darstellbare Wert für unsigned(unabhängig von der binären Darstellung) sein, was für das Zweierkomplement trivial gilt, jedoch nicht für andere Darstellungen.
Rubenvb
3
@ BillEvansatMariposa: Der Standard besagt, dass für vorzeichenbehaftete Ganzzahlen 3 Darstellungen zulässig sind: Vorzeichen + Größe, 2er-Komplement, 1er-Komplement. Jeder andere müsste für das Programm unsichtbar sein und als einer dieser 3 wahrgenommen werden.
Alexey Frunze
Ok aber unter der Haube! Was passiert WIRKLICH! Was ist der Unterschied zwischen einer signierten und einer nicht signierten Nummer? Wie verwaltet die Maschine die Berechnung? Es subtrahiert nur einen Wert vom anderen? Wie unterscheidet es 1111 = 15 und 1111 = -1?
Mihail Georgescu
18

intund unsigned intsind zwei verschiedene ganzzahlige Typen. ( intkann auch als signed intoder nur bezeichnet werden signed; unsigned intkann auch als bezeichnet werden unsigned.)

Wie die Namen andeuten, inthandelt es sich um einen vorzeichenbehafteten Ganzzahltyp und unsigned intum einen vorzeichenlosen Ganzzahltyp. Dies bedeutet, dass intnegative Werte und unsigned intnur nicht negative Werte dargestellt werden können.

Die C-Sprache stellt einige Anforderungen an die Bereiche dieser Typen. Der Bereich von intmuss mindestens -32767... sein +32767, und der Bereich unsigned intmuss mindestens 0... sein 65535. Dies bedeutet, dass beide Typen mindestens 16 Bit sein müssen. Sie sind 32 Bit auf vielen Systemen oder sogar 64 Bit auf einigen. inthat normalerweise einen zusätzlichen negativen Wert aufgrund der Zweierkomplementdarstellung, die von den meisten modernen Systemen verwendet wird.

Der vielleicht wichtigste Unterschied ist das Verhalten von vorzeichenbehafteter und vorzeichenloser Arithmetik. Bei signierten inthat der Überlauf ein undefiniertes Verhalten. Denn unsigned intes gibt keinen Überlauf; Jede Operation, die einen Wert außerhalb des Bereichs des Typs ergibt, wird beispielsweise umbrochen UINT_MAX + 1U == 0U.

Jeder ganzzahlige Typ, entweder mit oder ohne Vorzeichen, modelliert einen Teilbereich der unendlichen Menge mathematischer Ganzzahlen. Solange Sie mit Werten im Bereich eines Typs arbeiten, funktioniert alles. Wenn Sie sich der Unter- oder Obergrenze eines Typs nähern, stoßen Sie auf eine Diskontinuität und können unerwartete Ergebnisse erzielen. Bei vorzeichenbehafteten Ganzzahltypen treten die Probleme nur bei sehr großen negativen und positiven Werten auf, die INT_MINund überschreiten INT_MAX. Bei vorzeichenlosen Ganzzahltypen treten Probleme bei sehr großen positiven Werten und bei Null auf . Dies kann eine Fehlerquelle sein. Dies ist beispielsweise eine Endlosschleife:

for (unsigned int i = 10; i >= 0; i --) [
    printf("%u\n", i);
}

da iist immer größer oder gleich Null ist ; Das ist die Natur von Typen ohne Vorzeichen. (Wenn innerhalb der Schleife iNull ist, wird i--der Wert auf gesetzt UINT_MAX.)

Keith Thompson
quelle
12

Manchmal wissen wir im Voraus, dass der in einer bestimmten Ganzzahlvariablen gespeicherte Wert immer positiv ist - wenn er beispielsweise nur zum Zählen von Dingen verwendet wird. In einem solchen Fall können wir die Variable als unsigniert deklarieren, wie in , unsigned int num student;. Mit einer solchen Deklaration verschiebt sich der Bereich der zulässigen Ganzzahlwerte (für einen 32-Bit-Compiler) vom Bereich -2147483648 bis +2147483647 zum Bereich 0 bis 4294967295. Wenn Sie also eine Ganzzahl als vorzeichenlos deklarieren, verdoppelt sich die Größe der größtmöglichen fast Wert, den es sonst halten kann.

imran
quelle
@Alex Ich war gerade dabei, diese Antwort vor 10 Minuten zu bearbeiten und sie ist identisch. lol
Skuld
10

Für Laien ist ein vorzeichenloses int eine Ganzzahl, die nicht negativ sein kann und daher einen höheren Bereich positiver Werte aufweist, den sie annehmen kann. Ein vorzeichenbehaftetes int ist eine Ganzzahl, die negativ sein kann, aber einen niedrigeren positiven Bereich hat, wenn mehr negative Werte angenommen werden.

user2977636
quelle
0

In der Praxis gibt es zwei Unterschiede:

  1. Drucken (z. B. mit coutin C ++ oder printfin C): Die vorzeichenlose Ganzzahlbitdarstellung wird von den Druckfunktionen als nichtnegative Ganzzahl interpretiert.
  2. Bestellung : Die Bestellung hängt von der signierten oder nicht signierten Spezifikation ab.

Dieser Code kann die Ganzzahl anhand des Ordnungskriteriums identifizieren:

char a = 0;
a--;
if (0 < a)
    printf("unsigned");
else
    printf("signed");
Nano
quelle
Wenn dies den Unterschied erklärt, wenn einer mit negativen Zahlen handelt und der andere nicht. Es würde diesem Beitrag sehr helfen.
Daniel Jackson
@ DanielJackson Unklar, was Sie sagen. Ein Zeichen kann je nach Compiler als negativ oder positiv angesehen werden. Die Ausgabe des Codes hängt davon ab, was der Compiler auswählt. Dies zeigt den Unterschied zwischen vorzeichenbehaftet und vorzeichenlos.
Nano