Przypuśćmy, że mam numer 'numb'=1025 [00000000 00000000 00000100 00000001]
reprezentowaną :
Na maszynie Little-Endian:
00000001 00000100 00000000 00000000
Na maszynie Big-Endian:
00000000 00000000 00000100 00000001
Teraz, jeśli zastosuję lewy Shift na 10 bitach (tj .: numb << = 10), powinienem mieć:
[A] Na maszynie Little-Endian:
Jak zauważyłem w GDB, Little Endian wykonuje lewe przesunięcie w 3 krokach: [Pokazałem "3" kroki, aby lepiej zrozumieć tylko przetwarzanie]
Traktuj nie. w konwencji Big-Endian:
00000000 00000000 00000100 00000001
Zastosuj lewy Shift:
00000000 00010000 00000100 00000000
Przedstaw wynik ponownie w Little-Endian:
00000000 00000100 00010000 00000000
[B]. Na maszynie Big-Endian:
00000000 00010000 00000100 00000000
Moje pytanie brzmi:
Jeśli bezpośrednio zastosuję Przesunięcie w Lewo w Konwencji Little Endian, powinno to dać:
numb
:
00000001 00000100 00000000 00000000
numb << 10
:
00010000 00000000 00000000 00000000
Ale w rzeczywistości daje:
00000000 00000100 00010000 00000000
Aby osiągnąć tylko drugi wynik, powyżej pokazałem trzy hipotetyczne kroki.
Proszę wyjaśnić, dlaczego powyższe dwa wyniki są różne: Rzeczywisty wynik numb << 10
jest inny niż oczekiwany.
źródło
Nie, przesunięcie bitowe, jak każda inna część C, jest definiowane w kategoriach wartości , a nie reprezentacji. Przesunięcie w lewo o 1 to mnożenie o 2, przesunięcie w prawo to dzielenie. (Jak zawsze w przypadku operacji bitowych, uważaj na podpis. Wszystko jest najlepiej zdefiniowane dla typów całkowitych bez znaku).
źródło
x &= -1u << 20
najprawdopodobniej będzie niepoprawne, jeślix
jest 64-bitowe iint
32-bitowe. Z tego powodu GCC obiecuje nigdy nie traktować podpisanych zmian jako nieokreślonych lub nawet nieokreślonych.Każda instrukcja przesunięcia najpierw przesuwa bity wyższego rzędu, jest uważana za przesunięcie w lewo. Każda instrukcja przesunięcia najpierw przesuwa bity niższego rzędu, uważana jest za przesunięcie w prawo. W tym sensie zachowanie liczb
>>
i<<
dlaunsigned
liczb nie będzie zależało od endianizmu.źródło
Komputery nie zapisują liczb tak, jak my. Wartość po prostu się zmienia. Jeśli nalegasz, aby patrzeć na to bajt po bajcie (nawet jeśli komputer to nie robi), możesz powiedzieć, że na komputerze little-endian pierwszy bajt przesuwa się w lewo, nadmiarowe bity przechodzą do drugiego bajtu, i tak dalej.
(Nawiasem mówiąc, little-endian ma więcej sensu, jeśli zapiszesz bajty pionowo, a nie poziomo, z wyższymi adresami na górze. Tak się składa, że często rysuje się diagramy map pamięci).
źródło
Chociaż przyjęta odpowiedź wskazuje, że endianess jest pojęciem z punktu widzenia pamięci. Ale nie sądzę, aby to odpowiadało bezpośrednio na pytanie.
Niektóre odpowiedzi mówią mi, że operacje bitowe nie zależą od endianess , a procesor może reprezentować bajty w inny sposób. W każdym razie, mówi się o tym, że endianess zostaje wyabstrahowany.
Ale kiedy wykonujemy na przykład obliczenia bitowe na papierze, czy nie musimy w pierwszej kolejności podawać endianess? W większości przypadków wybieramy endianinę w sposób pośredni.
Na przykład załóżmy, że mamy taki wiersz kodu
0x1F & 0xEF
Jak obliczysz wynik ręcznie, na papierze?
Więc tutaj używamy formatu Big Endian do wykonania obliczeń. Możesz także użyć Little Endian, aby obliczyć i uzyskać ten sam wynik.
Przy okazji, kiedy piszemy liczby w kodzie, myślę, że jest to format Big Endian.
123456
lub0x1F
większość znaczących liczb zaczyna się od lewej strony.Ponownie, gdy tylko napiszemy jakiś format binarny wartości na papierze, myślę, że już wybraliśmy Endianess i oglądamy wartość tak, jak widzimy ją z pamięci.
Wracając do pytania, operację przesunięcia
<<
należy traktować jako przejście z LSB (najmniej znaczący bajt) do MSB (najbardziej znaczący bajt) .W takim razie jak na przykład w pytaniu:
numb=1025
Little Endian
LSB 00000001 00000100 00000000 00000000 MSB
Więc
<< 10
byłoby10bit
przejście od LSB do MSB.Porównanie i
<< 10
operacje dla formatu Little Endian krok po kroku:Łał! Otrzymuję oczekiwany wynik zgodnie z opisem PO!
Problemy, których PO nie przyniosła oczekiwanego rezultatu, są następujące:
Wygląda na to, że nie przeszedł z LSB na MSB.
Przesuwając bity w formacie Little Endian, powinieneś zdać sobie sprawę (dzięki Bogu, zdaję sobie z tego sprawę), że:
LSB 10000000 00000000 MSB << 1
jestLSB 00000000 00000001 MSB
, nieLSB 01000000 00000000 MSB
Ponieważ dla każdej osoby
8bits
faktycznie piszemy to w plikuMSB 00000000 LSB
Big Endian.Więc to jest jak
LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB
Podsumowując:
Chociaż mówi się, że operacje bitowe są wyodrębniane z blablablabla ..., kiedy ręcznie obliczamy operacje bitowe, nadal musimy wiedzieć, jakiego endianess używamy, gdy zapisujemy format binarny na papierze. Musimy również upewnić się, że wszyscy operatorzy używają tej samej endianess.
OP nie uzyskał oczekiwanego rezultatu, ponieważ źle wykonał zmianę biegów.
źródło