Jaka jest różnica między signed i unsigned int


91

Jaka jest różnica między wartością signed i unsigned int?


5
To jest prawdziwe pytanie, a odpowiedź nie jest taka prosta, ale raczej subtelna.
R .. GitHub STOP HELPING ICE

Głosowanie za ponownym otwarciem. Może to być duplikat, ale z pewnością jest to prawdziwe pytanie.
Brian


Należy dodać więcej tagów, ponieważ używa ich wiele języków.
Juan Boero

To pytanie może wymagać rozwinięcia rozdziału. Jeśli chcesz poznać tajniki, sprawdź liczby całkowite bez znaku i ze znakiem, aby uzyskać więcej wyjaśnień.
anonimowy

Odpowiedzi:


113

Jak zapewne wiesz, ints są wewnętrznie przechowywane w postaci binarnej. Zwykle intzawiera 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 intczy 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 ints najbardziej znaczący bit występuje 1wtedy i tylko wtedy, gdy liczba jest ujemna. Dlatego dla signed ints ten bit jest nazywany „bitem znaku”.


11
Być może warto zauważyć, że jest to format dopełnienia tych dwóch, który wprawdzie jest obecnie szeroko stosowany. Istnieją również inne sposoby przedstawiania liczb całkowitych ze znakiem, w szczególności dopełnienia.
Schedler

Poprawny. A standard ISO9899 C nie wymaga nawet, aby używać dopełnienia jednego lub dwóch; każda inna konwencja, która faktycznie działa, jest dozwolona.
Bill Evans w Mariposa

1
Chociaż uzupełnienie do dwóch nie jest wymagane, (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.
rubenvb

3
@BillEvansatMariposa: Standard mówi, że dla liczb całkowitych ze znakiem są dozwolone 3 reprezentacje: znak + wielkość, dopełnienie do 2, dopełnienie do 1. Każdy inny musiałby być niewidoczny dla programu i być postrzegany jako jeden z tych 3.
Alexey Frunze

Ok, ale pod maską! Co NAPRAWDĘ się dzieje! Jaka jest różnica między numerem PODPISANY a NIEPISANY! W jaki sposób maszyna zarządza obliczeniami? Po prostu odejmuje wartość od drugiej? Jak to różnice 1111 = 15 i 1111 = -1?
Mihail Georgescu

19

inti unsigned intsą dwoma różnymi typami liczb całkowitych. ( intmoże być również określane jako signed intlub po prostu signed; unsigned intmoże być również określane jako unsigned.)

Jak sugerują nazwy, intjest podpisana typ całkowitą, i unsigned intjest niepodpisany typu całkowitą. Oznacza to, że intmoże reprezentować wartości ujemne i unsigned intmoże przedstawiać tylko wartości nieujemne.

Język C nakłada pewne wymagania na zakresy tego typu. Zakres intmusi być co najmniej -32767.. +32767, a zakres unsigned intmusi 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. intzwykle 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 intprzepełnienie ma niezdefiniowane zachowanie. Bo unsigned intnie 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_MINi 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ż ijest zawsze większe lub równe zero; taka jest natura typów bez znaku. (Wewnątrz pętli, gdy iwynosi zero, i--ustawia swoją wartość na UINT_MAX.)


12

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.


@Alex Byłem w trakcie redagowania odpowiedzi 10 minut temu i jest identyczny. lol
Skuld

12

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ąć.


0

W praktyce istnieją dwie różnice:

  1. drukowanie (np. coutw C ++ lub printfC): reprezentacja bitowa w postaci liczby całkowitej bez znaku jest interpretowana jako nieujemna liczba całkowita przez funkcje drukowania.
  2. Zamawianie : zamówienie zależy od podpisanej lub niepodpisanej specyfikacji.

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");

Jeśli to wyjaśniało różnicę, gdy jeden ma do czynienia z liczbami ujemnymi, a drugi, nie. Bardzo by pomogło w tym poście.
Daniel Jackson

@DanielJackson Niejasne, co mówisz. znak można uznać za ujemny lub dodatni w zależności od kompilatora. dane wyjściowe kodu zależą od tego, co wybierze kompilator, a to pokazuje różnicę między podpisanymi i bez znaku.
Minimus Heximus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.