One little, two little, three little endians…

December 24, 2006 on 12:58 pm | In Programing |

Víte co mají společného čísla -2030043136 a 135? Taky jsem nevěděl, přišel jsem na to až po více než 40 minutách.

Jsou to totiž v podstatě stejná čísla :-) Jen je u nich zaměněno pořadí bytů v paměti. O co jde? Paměť PC je rozdělena na jednotky. Tyto adresovatelné jednotky se nazývají byty [čti bajty]. 1 byte má 8 bitů [čti bitů] - z toho tedy vyplývá, že maximalní hodnota, která se dá na jedno místo uložit je 255. My samozdřejmě potřebujeme pracovat s většími celky než 1 byte a proto se díváme na více za sebou jdoucích bytů jako na jednu spojitou část. No a právě zde je kámen úrazu. Čísla, o kterých jsem se zmínil na začátku, jsou uložena do čtyř bytů, tedy do 4 po sobě jdoucích jednotek. Jenže ony jsou dva způsoby jak toto více bytové číslo uložit. V tabulce je vyobrazeno číslo 135 převedené do dvojkové soustavy a rozepsané do jednotlivých paměťových buněk.

adresa big endian little endian
5678 00000000 10000111
5679 00000000 00000000
567A 00000000 00000000
567B 10000111 00000000

Big endian
Je způsob, kdy se na nižší adresu dávají vyšší řády čísla. Používá se třeba na procesorech od Motoroly.
Little endian
Je přesně opačný - na nižší adresy se dávají nižší řády čísla, tento způsob používají nám dobře známe intelácke procesory a samodřejmě i AMDčka.

Na tyto dva odlišné způsoby je potřeba dávat si pozor právě u síťové komunikace, protože tady si nemůžete být jistí, co je na druhé straně za mašinu. Třeba komunikace mezi jednotlivými účastníky sítě bittorrent posílá data jako big-endian a to i přesto, že většina počítačů, na kterých klienti běží používají little-endian!

Převodník
Vytvořit fci, která data převede big-endian na little-endian a opačně je jednoduché:

void preved_endian(unsigned char *source, unsigned char *destination, int size)
{
// Counter
int x;
// Reverse all the bytes
for(x = 0; x < size; x++)
destination[x] = source[size - x - 1];
}

Potřebujete-li tedy přehodit třeba integer, tak stačí zavolat preved_endian(&zdroj, &cil, sizeof(int)); No možná by ještě pro umlčení compileru bylo dobré ukazatele přetypovat - (unsigned char *) &zdroj.

3 Comments »

RSS feed for comments on this post. TrackBack URI

  1. Pozor, ta funkce ti převrátí bity a ne byty.

    Comment by Ondřej Garncarz — 2006-12-25 #

  2. To neni pravda. Podivej se na tu tabulku - poradi bitu v bytu je stale stejne! Pouze prevrati ulozeni jednotlivych bytu v dane casti pameti.

    Comment by jarcec — 2006-12-25 #

  3. Jej, pardon, jsem vnímal “source” jako pole bitů.

    Comment by Ondřej Garncarz — 2006-12-25 #

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds. Valid XHTML and CSS. ^Top^