Jaka jest różnica między wartością signed i unsigned int?
Jaka jest różnica między wartością signed i unsigned int?
Odpowiedzi:
Jak zapewne wiesz, int
s są wewnętrznie przechowywane w postaci binarnej. Zwykle int
zawiera 32 bity, ale w niektórych środowiskach może zawierać 16 lub 64 bity (lub nawet inną liczbę, zwykle, ale niekoniecznie, potęgę dwóch).
Ale w tym przykładzie spójrzmy na 4-bitowe liczby całkowite. Mały, ale przydatny do celów ilustracyjnych.
Ponieważ taka liczba całkowita ma cztery bity, może przyjąć jedną z 16 wartości; 16 to 2 do czwartej potęgi, czyli 2 razy 2 razy 2 razy 2. Jakie to są wartości? Odpowiedź zależy od tego, czy ta liczba całkowita to a signed int
czy an unsigned int
. Z unsigned int
, wartość nigdy nie jest ujemny; nie ma znaku związanego z wartością. Oto 16 możliwych wartości czterobitowych 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
... a oto 16 możliwych wartości czterobitowego 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
Jak widać, dla signed int
s najbardziej znaczący bit występuje 1
wtedy i tylko wtedy, gdy liczba jest ujemna. Dlatego dla signed int
s ten bit jest nazywany „bitem znaku”.
(unsigned)(-1)
musi być maksymalną reprezentowalną wartością dla unsigned
(niezależnie od reprezentacji binarnej), co jest trywialnie prawdziwe dla uzupełnień do 2, ale nie dla innych reprezentacji.
int
i unsigned int
są dwoma różnymi typami liczb całkowitych. ( int
może być również określane jako signed int
lub po prostu signed
; unsigned int
może być również określane jako unsigned
.)
Jak sugerują nazwy, int
jest podpisana typ całkowitą, i unsigned int
jest niepodpisany typu całkowitą. Oznacza to, że int
może reprezentować wartości ujemne i unsigned int
może przedstawiać tylko wartości nieujemne.
Język C nakłada pewne wymagania na zakresy tego typu. Zakres int
musi być co najmniej -32767
.. +32767
, a zakres unsigned int
musi być co najmniej 0
.. 65535
. Oznacza to, że oba typy muszą mieć co najmniej 16 bitów. W wielu systemach mają 32 bity, w niektórych nawet 64 bity. int
zwykle ma dodatkową wartość ujemną ze względu na reprezentację dopełnienia do dwóch używaną w większości nowoczesnych systemów.
Być może najważniejszą różnicą jest zachowanie arytmetyki ze znakiem i bez znaku. W przypadku podpisanego int
przepełnienie ma niezdefiniowane zachowanie. Bo unsigned int
nie ma przelewu; każda operacja, która zwraca wartość spoza zakresu typu zawija się wokół, na przykład UINT_MAX + 1U == 0U
.
Dowolny typ liczb całkowitych, ze znakiem lub bez, modeluje podzakres nieskończonego zbioru matematycznych liczb całkowitych. Dopóki pracujesz z wartościami w zakresie typu, wszystko działa. Kiedy zbliżasz się do dolnej lub górnej granicy typu, napotykasz nieciągłość i możesz uzyskać nieoczekiwane wyniki. W przypadku liczb całkowitych ze znakiem problemy występują tylko w przypadku bardzo dużych wartości ujemnych i dodatnich, przekraczających INT_MIN
i INT_MAX
. W przypadku typów całkowitych bez znaku problemy występują przy bardzo dużych wartościach dodatnich i przy zerze . Może to być źródłem błędów. Na przykład jest to nieskończona pętla:
for (unsigned int i = 10; i >= 0; i --) [
printf("%u\n", i);
}
ponieważ i
jest zawsze większe lub równe zero; taka jest natura typów bez znaku. (Wewnątrz pętli, gdy i
wynosi zero, i--
ustawia swoją wartość na UINT_MAX
.)
Czasami wiemy z góry, że wartość przechowywana w danej zmiennej całkowitej będzie zawsze dodatnia - np. Gdy jest używana tylko do liczenia rzeczy. W takim przypadku możemy zadeklarować zmienną być niepodpisany, jak w, unsigned int num student;
. Przy takiej deklaracji zakres dopuszczalnych wartości całkowitych (dla kompilatora 32-bitowego) przesunie się z zakresu od -2147483648 do +2147483647 do zakresu od 0 do 4294967295. W ten sposób zadeklarowanie liczby całkowitej jako bez znaku prawie podwaja rozmiar największego możliwego wartość, którą może utrzymać w inny sposób.
W kategoriach laików bez znaku int jest liczbą całkowitą, która nie może być ujemna, a zatem ma wyższy zakres wartości dodatnich, niż może przyjąć. Wartość int ze znakiem to liczba całkowita, która może być ujemna, ale ma niższy zakres dodatni w zamian za bardziej ujemne wartości, jakie może przyjąć.
W praktyce istnieją dwie różnice:
cout
w C ++ lub printf
C): reprezentacja bitowa w postaci liczby całkowitej bez znaku jest interpretowana jako nieujemna liczba całkowita przez funkcje drukowania.ten kod może zidentyfikować liczbę całkowitą za pomocą kryterium porządkowania:
char a = 0;
a--;
if (0 < a)
printf("unsigned");
else
printf("signed");