2010-09-08 12 views
8
signed int x= -5; 
unsigned int y=x; 

jaka jest wartość y? i jak?Wartości niepodpisane i podpisane w C (jaka jest wydajność)

+5

Kiedy próbowałem, co widziałeś? –

+4

@KennyTM, nie zdefiniowano implementacji; rzutowanie z unsigned int na podpisany int, który nie może go reprezentować, to zdefiniowanie implementacji, ale na odwrót (signed -> unsigned) jest dobrze zdefiniowane. – bdonlan

+2

@bdonlan: 'UINT_MAX' * jest * zdefiniowana implementacja. – kennytm

Odpowiedz

-1

Y = 0xfffffffb jest binarna reprezentacja -5 (uzupełnienie dwójkowe)

+0

Czy mógłbyś wyjaśnić więcej ... –

+1

Wynik nie zależy od "reprezentacji binarnej". Wynik jest podyktowany wymaganiami standardu językowego. W tym przypadku standard jest dość wyraźny. – AnT

+0

@AndreyT. Aby być sprawiedliwym, chociaż nie jest to powiedziane w ten sposób, to z pewnością prawdą jest, że dopełnienie 2 -> unsigned conversion daje ten sam wzorzec bitowy (myślę, że standard C++ wspomina o tym na marginesie, nie pamięta, czy standard C). Opis Philiberta jest równoznaczny z definicją zawartą w standardzie: możesz konwertować podpis -> unsigned przez wyliczenie uzupełnienia 2 do podpisanej wartości, a następnie odczytanie jej jako wartości unsigned. Nigdy nie powiedział, że tak właśnie działa implementacja (chociaż bez wątpienia implementacje uzupełnień 2). –

16

Zależy to od wartości maksymalnej unsigned int. Zazwyczaj unsigned int jest 32-bitowy długości, tak UINT_MAX wynosi 2 − 1. Standard C (§ 6.3.1.3/2) wymaga podpisany → unsigned konwersja może być wykonywane jak

przeciwnym razie, jeśli nowy typ jest niepodpisany, wartość jest konwertowana przez wielokrotne dodawanie lub odejmowanie o jeden więcej niż maksymalna wartość, która może być reprezentowana w nowym typie, dopóki wartość nie znajdzie się w zakresie nowego typu.

Tak więc Y = X + ((2 − 1) + 1) = 2 − 5 = 4294967291.


na platformie 2's complement, które są w większości implementacji w dzisiejszych czasach, y jest również taki sam jak uzupełnienie do 2-go uzupełnienia x.

-5 ~ = 5 + 1 = 0xFFFFFFFA + 1 = 0xFFFFFFFB = 4294967291.

2

Wartość y jest UINT_MAX - 5 + 1 tj UINT_MAX - 4.

Po przekonwertowaniu liczby całkowitej ze znakiem na typ bez znaku, wartość jest zmniejszana modulo 2^N, gdzie N jest liczbą bitów tworzących wartość w typie bez znaku. Dotyczy to zarówno wartości liczbowych ujemnych, jak i dodatnich.

Jeśli konwersja podpisanych typu do unsigned o tej samej wielkości, powyższe oznacza, że ​​korzystne wartości ze znakiem pozostają bez zmian (+5 przechodzi na 5, na przykład), a wartości ujemne dodane do MAX + 1, gdzie MAX jest maksymalna wartość niepodpisanego typu (-5 zostaje przekształcona na MAX + 1 - 5).

4

od standardu C99:

6.3.1.3 Signed całkowitymi bez znaku i

  1. Jeśli wartości z liczby całkowitej typu przekształca się w inny rodzaj całkowitej inny niż _Bool jeśli wartość może być reprezentowany przez nowy typ, pozostaje niezmieniony.
  2. przeciwnym razie, jeżeli nowy typ jest podpisany wartość jest przekształcany przez kilkakrotnie dodając lub odjęcie o jeden więcej niż wartość maksymalna, która może być reprezentowana w nowego typu do wartości w zakresie nowego typu . 49)

49) Zasady opisują arytmetycznie wartość matematyczną, a nie wartość danego typu wyrażenia.

Będziesz więc skutecznie sprawdzać, y = x + UINT_MAX + 1.

Po prostu oznacza to, że reprezentacja uzupełnienia dwójki jest używana jako niezmieniona jako liczba całkowita bez znaku, co czyni ją bardzo szybką na większości współczesnych komputerów, ponieważ używają one dwójki-uzupełnienia dla liczb całkowitych ze znakiem.

+3

Brakuje jednego: UINT_MAX to 2^N-1. –

+0

Nie do końca poprawne. Prawidłowa formuła to 'y = x + UINT_MAX - 1'. – AnT

+1

@AndreyT: Właściwie poprawna formuła to 'y = x + UINT_MAX + 1'. – kennytm

1

Podpisane wartości są zwykle przechowywane jako coś, co nazywa two's complement: numery

uzupełnienie dwójkowe są sposobem kodowania liczb ujemnych w zwykłym binarny tak, że dodatek nadal działa. Dodawanie -1 + 1 powinno być równe 0, ale zwykłe dodawanie daje wynik 2 lub -2, chyba że operacja zwraca szczególną uwagę na bit znaku i zamiast tego wykonuje odejmowanie. Uzupełnienie dwóch daje prawidłową sumę bez tego dodatkowego kroku.

Oznacza to, że rzeczywisty reprezentację liczb -5 4294967291 w pamięci (na słowa 32 bitów) są identyczne, na przykład: 0xFFFFFFFB lub 0b11111111111111111111111111111011. kiedy tak zrobić:

unsigned int y = x; 

Zawartość X jest dosłownej tj bitowe do y. Oznacza to, że jeśli przejrzysz surowe wartości w pamięci x i y, będą one identyczne. Jeśli jednak zrobić:

unsigned long long y1 = x; 

wartość x zostanie przedłużony logowania przed konwertowane do unsigned long long. W typowym przypadku, gdy długo trwa 64 bity, oznacza to, że y1 jest równy 0xFFFFFFFFFFFFFFFB.

Należy pamiętać, co dzieje się podczas rzutowania na większy typ. Podpisana wartość rzucana do większej podpisanej wartości zostanie przedłużona znakiem. Tak się nie stanie, jeżeli wartość źródłowa jest niepodpisany, np .:

unsigned int z = y + 5; 
long long z1 = (long long)x + 5; // sign extended since x is signed 
long long z2 = (long long)y + 5; // not sign extended since y is unsigned 

z i z1 będzie równy 0, ale z2 nie będzie. Można temu zaradzić poprzez odlanie wartość podpisanej przed rozszerzając go:

long long z3 = (long long)(signed int)y + 5; 

lub analogicznie jeśli nie chcą przedłużenia znak wystąpić:

long long z4 = (long long)(unsigned int)x; 
+1

Ale pytanie dotyczy konwersji na * niepodpisany * typ. Jednak w odpowiedzi podajesz konwersje tylko do * podpisanych * typów. – AnT

+0

Błagam, by się różnił, choć skupiam się nieco na konwersjach na typy podpisane, bo tam są smoki. Nie sądzę też, że moja odpowiedź zasługuje na pochwałę, ale jestem stronniczy. –

+0

+1: dla "uzupełnienia dwójki", nawet jeśli w rzeczywistości wymijające sformułowanie C99 daje definicję, która działałaby również z kompilatorem, który użyłby powiedzmy BCD.Zastanawiam się, czy taki kompilator C istnieje mimo to, dopóki nie udowodniłem, że jest błędny. Uważam, że wszystkie obecnie istniejące kompilatory C używają uzupełnienia dwójkowego. – kriss

Powiązane problemy