Byłem ciekawy, co się stanie, jeśli przypiszę wartość ujemną do zmiennej bez znaku.
Kod będzie wyglądał mniej więcej tak.
unsigned int nVal = 0;
nVal = -5;
Nie dało mi to żadnego błędu kompilatora. Kiedy uruchomiłem program, nVal
przypisano mu dziwną wartość! Czy to możliwe, że przypisywana jest wartość uzupełnienia jakiejś dwójki nVal
?
nVal = (unsigned int) -5;
. Obsada-5
Dounsigned int
jest zdefiniowany w 6.3.1.3. Reprezentacja w uzupełnieniu do 2s nie jest narzucona przez standard, ale algorytm konwersji na bez znaku to: „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 ”.Odpowiedzi:
Do oficjalnej odpowiedzi - sekcja 4.7 konw. Integralna
Zasadniczo oznacza to, że jeśli podstawowa architektura przechowuje w metodzie, która nie jest dopełnieniem Two (np. Signed Magnitude lub One's Complement), to konwersja na unsigned musi zachowywać się tak, jakby była dopełnieniem Two.
źródło
Przypisuje wzorzec bitowy reprezentujący -5 (w uzupełnieniu do 2) int bez znaku. Która będzie dużą wartością bez znaku. W przypadku 32-bitowych liczb całkowitych będzie to 2 ^ 32 - 5 lub 4294967291
źródło
ceil(log_2(x))
.)Wyświetli się jako dodatnia liczba całkowita o wartości maksymalnej liczby całkowitej bez znaku - 4 (wartość zależy od architektury komputera i kompilatora).
BTW
Możesz to sprawdzić pisząc prosty program w C ++ typu „hello world” i przekonaj się sam
źródło
Masz rację, liczba całkowita ze znakiem jest przechowywana w postaci uzupełnienia do 2, a liczba całkowita bez znaku jest przechowywana w reprezentacji binarnej bez znaku . C (i C ++) nie rozróżnia tych dwóch, więc wartość, którą otrzymujesz, jest po prostu wartością binarną bez znaku reprezentacji binarnej uzupełnienia do 2.
źródło
Tak, masz rację. Rzeczywista przypisana wartość jest podobna do wszystkich ustawionych bitów z wyjątkiem trzeciego. -1 to wszystkie ustawione bity (szesnastkowo: 0xFFFFFFFF), -2 to wszystkie bity oprócz pierwszego i tak dalej. To, co zobaczysz, to prawdopodobnie wartość szesnastkowa 0xFFFFFFFB, która dziesiętnie odpowiada 4294967291.
źródło
Kiedy przypisujesz wartość ujemną do zmiennej bez znaku, używa ona metody dopełnienia 2 do jej przetworzenia iw tej metodzie zamienia wszystkie 0 na 1 i wszystkie 1 na 0, a następnie dodaje do niej 1. W twoim przypadku masz do czynienia z wartością int, która ma 4 bajty (32 bity), więc próbuje użyć metody uzupełniania 2 na liczbie 32-bitowej, co powoduje odwrócenie wyższego bitu. Na przykład:
┌─[student@pc]─[~] └──╼ $pcalc 0y00000000000000000000000000000101 # 5 in binary 5 0x5 0y101 ┌─[student@pc]─[~] └──╼ $pcalc 0y11111111111111111111111111111010 # flip all bits 4294967290 0xfffffffa 0y11111111111111111111111111111010 ┌─[student@pc]─[~] └──╼ $pcalc 0y11111111111111111111111111111010 + 1 # add 1 to that flipped binarry 4294967291 0xfffffffb 0y11111111111111111111111111111011
źródło