2010-02-11 7 views
8

Powiedzmy, że mam 4Brytową liczbę całkowitą i chcę ją przesłać do 2 bajtowej krótkiej liczby całkowitej. Czy mam rację, że w krótkiej całkowitej liczbie całkowitej (mała i duża endiana) będą się składać z 2 najmniej znaczących bajtów tej 4-bajtowej liczby całkowitej?Little endian Vs Big endian

Drugie pytanie:
Jaki będzie wynik takiego kodu w małym procesorze endian i big endian?

int i = some_number; 
short s = *(short*)&i; 

IMHO w big endian procesor 2 najbardziej znaczących bajtów zostanie skopiowana, a little endian 2 najmniej znaczące bajty zostaną skopiowane.

+0

Proponuję użyć matematyki, aby zmniejszyć liczbę do odpowiedniego zakresu (rozmiaru) przed kopiowaniem. Kompilatory utrzymają Endianness, więc nie będziesz mieć wielu zmartwień. Kopiowanie fragmentów zmiennych skutkuje niepokojem o Endianness. –

Odpowiedz

12

Czy mam rację, że w obu krótkich całkowitych będzie się składać z 2 najmniej znaczących bajtów tej 4-bajtowej liczby całkowitej?

Tak, z definicji.

Różnica między bigE i littleE polega na tym, czy najmniej znaczący bajt znajduje się na najniższym adresie, czy nie. Na małym procesorze endian, najniższe adresy są najmniej znaczącymi bitami, x86 robi to w ten sposób.

one dać taki sam efekt na małej E.

short s = (short)i; 
short s = *(short*)&i; 

na dużym procesorem endian, najwyższe adresy są najmniej znaczące bity, 68000 Power PC i zrobić to w ten sposób (w rzeczywistości Power PC może być zarówno , ale maszyny PPC firmy Apple korzystać Bige)

one dają ten sam rezultat na dużym E.

short s = (short)i; 
short s = ((short*)&i)[1]; // (assuming i is 4 byte int) 

Więc, jak widać, niewiele endian pozwala uzyskać u leas t znaczące bity operandu , nie wiedząc, jak duży jest on. niewiele E ma zalety dla zachowania kompatybilności wstecznej.

Jaka jest przewaga dużego endianina? Tworzy zrzuty heksadecymalne, które są łatwiejsze do odczytania.

Naprawdę inżynierowie firmy Motorola uważali, że zmniejszenie obciążenia podczas odczytywania zrzutów heksadecymalnych jest ważniejsze niż kompatybilność wsteczna. Inżynierowie z Intela wierzyli w coś wręcz przeciwnego.

+0

Nie jestem pewien, czy argument kompatybilności wstecznej jest bardzo silny, ponieważ programy, które niepoprawnie przyjmują, że niektóre zmienne mają określony rozmiar, najprawdopodobniej zostaną złamane z innych powodów, nawet na małej maszynie endianowej (na przykład w przypadku macierzy). Wydaje mi się, że ma to więcej wspólnego z ułatwianiem pewnych optymalizacji niskiego poziomu i innych sztuczek wewnątrz kompilatora lub sprzętu. –

+0

@Josef: Tak, jestem pewna, że ​​było wiele drobnych powodów, dla których projektanci sprzętu wolą małe litery E, a kompatybilność może nie być dla nich tak ważna. Okazuje się jednak, że miało to duże znaczenie przy przejściu z 80886 do 286/386. Kod napisany dla 8088 nadal działa na nowoczesnych procesorach x86/x64. –

+0

Tak, architektury x86 są kompatybilne wstecznie na poziomie binarnym, według projektu (na dobre i na złe), zawsze zachowując cały zestaw instrukcji poprzednich generacji. Prawdą jest, że graniczy to z moim obszarem ekspertyzy, ale czy niewiele endianów pomaga w tym zakresie, poza tym, że może trochę uprościć logikę obwodów dla instrukcji mov? Nadal masz różne kody opcyjne dla różnych rozmiarów danych (bajt, słowo, dwór itp.). –

2
  1. Tak. Kiedy konwertujesz wartości, nie musisz się martwić o endianię.

  2. Tak. Kiedy konwertujesz wskaźniki, robisz to.

+0

Zasadniczo jedyną potrzebą przekształcania wskaźników w taki sposób, który ma znaczenie, jest serializowanie danych (to jest plików lub sieci we/wy). Ale w takim przypadku naprawdę musisz się martwić, ponieważ czytelnik może użyć innej endianness. –

1

Przede wszystkim, może już to wiedzą, ale pozwól mi wspomnieć, że rozmiar int nie jest gwarancją, że 4 bajty i krótkich, 2 bajty na wszystkich platformach.

Jeśli w swoim pierwszym pytaniu chodziło Ci o coś takiego:

int i = ...; 
short s = (short)i; 

to tak, s będzie zawierała mniejszą bajt (y) i.

Myślę, że odpowiedź na twoje drugie pytanie również brzmi: tak; na poziomie bajtów w grę wchodzi endianness systemu.

1

Trzeba mieć świadomość, że swoim drugim przykładzie

int i = some_number; 
short s = *(short*)&i; 

nie jest poprawny kod C, gdyż jest niezgodny surowe zasady aliasingu. Prawdopodobnie zakończy się niepowodzeniem w niektórych poziomach optymalizacji i/lub kompilatorach.

Stosować że związki o:

union { 
    int i; 
    short s; 
} my_union; 

my_union.i = some_number; 
printf("%d\n",my_union.s); 

Ponadto, jak inni zauważyć, nie można zakładać, że ints będzie 4 bajtów. Lepiej użyj int32_t i int16_t, gdy potrzebujesz określonych rozmiarów.

+0

W jaki sposób narusza ścisłe aliasing? –

+1

Pisanie do jednego członka związku i czytanie z innego to UB. – dalle

+0

nie jest to naruszenie aliasingu. po prostu podważa system typów, nigdy nie tworzy wskaźnika. –

1

Jeśli naprawdę chcesz przekonwertować int do krótkiego, a potem po prostu to zrobić:

short int_to_short(int n) { 
    if (n < SHRT_MIN) return SHRT_MIN; 
    if (n > SHRT_MAX) return SHRT_MAX; 
    return (short)n; 
} 

Nie musisz nawet martwić endian, język obsługuje to za Ciebie. Jeśli jesteś pewien, że n znajduje się w zasięgu krótkiego, możesz pominąć także czek.

+0

Nie martwię się, byłem tylko ciekawy, jaki byłby rezultat. –

Powiązane problemy