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

91

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

Moumita Das
źródło
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
4
Re: „To może być duplikat” - Jaka jest różnica między unsigned int i signed int w C?
eldarerathis
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”.

Bill Evans z Mariposa
źródło
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.)

Keith Thompson
źródło
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.

imran
źródło
@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ąć.

user2977636
źródło
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");
Minimus Heximus
źródło
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