A számítástechnikában az angol endianness kifejezés (mivel nincs általánosan elfogadott magyar megfelelője, így talán a bájtsorrend a legjobb fordítás) arra a tulajdonságra utal, amely meghatározza bizonyos adatok – többnyire kisebb egységek sorozatának – tárolási és/vagy hálózati továbbítási sorrendjét. Ez a tulajdonság különösen fontos az integer értékek memóriában való bájtonkénti tárolása (egy adott memóriacímhez képest), illetve azok hálózaton vagy más adathordozón keresztüli továbbítása során. Számítógépek esetében, ha kifejezetten bájtokról beszélünk, akkor az endiannes egyszerűen a bájtsorrendre, ritkábban a byte sex-re vonatkozik. Az eredeti angol kifejezés utalás egy képzeletbeli konfliktusra, amely Jonathan Swift Gulliver utazásai című könyvében jelenik meg. A két ellentétes csoport közül az egyik szerint a lágytojás nagyobb végét (big-endian), míg a másik szerint a kisebb végét (little-endian) kell feltörni.

Bájtsorrend a számítógépeken Úgy tűnik, egyik tárolási mód sem jelent kifejezett előnyt a másikkal szemben, és mindkettőnek megvannak a követői különböző számítógép-architektúrákban. Bár kijelenthetjük, hogy jelenleg inkább a növekvő bájtsorrend van túlsúlyban, mivel az Intel x86 alapú processzorok (és azok klónjai) – amelyeket a legtöbb személyi számítógép és laptop használ – a növekvő bájtsorrendet, azaz a „kicsi elöl” (little-endian) módszert alkalmazzák. Ez a megoldás gyakran „Intel formátum” néven is ismert.

A hálózatok ezzel szemben általában „nagy az elején” (big-endian) tulajdonságú, azaz csökkenő bájtsorrendű számokat használnak a csomagcímekben; ez történetileg alakult így, mivel ez a megoldás lehetővé tette az útvonal-irányítást (routing) telefonszámok alapján. A Motorola processzorok jellemzően a csökkenő bájtsorrendű – „nagy az elején” (big-endian) – tárolást alkalmazzák, míg azonban az ARM és számos más modern architektúra is képes átkapcsolni a bájtsorrendet, ami különösen előnyös lehet például hálózati eszközök esetében a nagyobb teljesítmény érdekében.

Általában egy bájt tekinthető az alapvető egységnek a tárolás vagy az adatátviteli protokollok szempontjából. Ezért az egy bájtos adatok sorozata – például ASCII kódolású szöveg, UTF-8 vagy az ISO 8859 kódolás valamelyik változata – jellemzően nem érintett a bájtsorrend okozta problémákban. Másrészről a szövegek változó-hosszúságú kódolása, mint például az UTF-8, amelyek a bájtot használják egységként, már tartalmazhat „beépített” bájtsorrend problémákat, bár csaknem minden általánosan használt kódolási eljárás figyelembe vette ezt a kérdést a tervezés során. A Unicode stringek UTF-16 vagy UTF-32 szerinti kódolása viszont már érintett a bájtsorrend problámájában, mivel minden kód egység két vagy négy bájtot képvisel.

Logikai és aritmetikai leírás

Megjegyzés: a következő fejezetben minden szám hexadecimális formában szerepel. Nagy az elején – Big-endian

Amikor egy (számos) számítógép 32 bites egész értéket tárol a memóriájában (ami legyen esetünkben 4A3B2C1D, a 100-as címtől kezdve), ahol a memória 1 bájtos elemi tárolókból áll, és a címek bájtonként növekednek, a tárolás a következőképpen történik:

100 101 102 103 … 4A 3B 2C 1D …

Ebben az esetben, a legnagyobb helyiértékű bájt – angolul most significant byte, rövidítve MSB - (ami esetünkben 4A) a memóriában a legalacsonyabb címen van tárolva, míg az eggyel kisebb helyiértékű (3B) a következő címen, és így tovább.

A továbbiakban lépjünk tovább az elemi tárolók méreteinek vonatkozásában: tegyük fel, hogy továbbra is 32 bites értéket kell tárolni, de most a tárolás elemi egységének 2 bájtot tekintsünk, a memóriacím 2 bájtonként 1-gyel nő. Azonos példánál maradva (4A3B2C1D értéket a 100-as címtől kezdve), a 100-tól 101-ig terjedő címtartományban kell tárolni, ahogyan azt a következő példa mutatja:

100 101 … 3B 4A 1D 2C …

A legnagyobb helyiértékű adat a példában most 4A3B, amit a 2C1D érték követ a 101-es címen.

A harmadik példa célja: vizsgálni a különbséget, amit az elemi tároló elem és a tárolási lépés hosszának változása okozhat. Ebben a példában is 32 bites egészet kell tárolni a memóriában, 2 bájtos elemi tárolóelem hossz, és bájtonkénti címnövelés esetén (tehát a memóriacím 2 bájtonként 2-vel nő):

100 102 … 3B 4A 1D 2C …

A legnagyobb helyiértékű adat most is 4A3B a példában, amit a 2C1D érték követ, de most a 102 címen.

Azokat az architektúrákat, amelyek a fenti szabályokat követik, nevezik „nagy az elején” vagy angolul big-endian bájtsorrendűeknek (az angol end jelen esetben a kezdő véget jelenti, tehát a memorizáláshoz: a nagy vég lesz az első helyen) ide tartoznak a Motorola 68000, SPARC, PowerPC (az Intel-re való áttérés előtt az Apple Macintosh processzora volt), és a System/370.

Más számítógépek a 4A3B2C1D értéket a következő bájtsorrenddel tárolják:

Kicsi az elején – Little-endian 100 101 102 103 … 1D 2C 3B 4A …

Így, a legkisebb helyiértékű byte (least significant byte, rövidítve LSB) az első, és ez példánkban 1D.

100 101 102 103 … 1D 2C 3B 4A …

A legkisebb helyiértékű adathoz most a 2C1D érték tartozik a példánkban, ezt követi a 4A3B a 101-es címen.

100 101 … 1D 2C 3B 4A …

A legkisebb helyiértékű adat még mindig a 2C1D a példánkban, amit a 4A3B érték követ a 102 címen.

A fenti tárolási módot követő architektúrákat nevezik „kicsi az elején” vagy angol kifejezéssel little-endian (mnemonic: „little end in” – the little end goes in first, a kis vég kerül előre) bájtsorrendűeknek, ide tartoznak többek között a MOS Technology 6502, DEC VAX, és legtöbbet emlegetett Intel x86 alapú processzor család tagjai, ideértve az Intel Pentium alapú személyi számítógép és laptop processzorokat is.

Egyszerűbben fogalmazva, a bájtsorrend nem a vég értékét határozza meg, hanem inkább azt, hogy melyik vég kerül hová.

Kettős bájtsorrend – Bi-endianness

Egyes architektúrák esetében beállítható vagy egyik, vagy másik bájtsorrend; ide tartoznak az ARM, PowerPC (kivéve a PPC970/G5), DEC Alpha, MIPS, PA-RISC és az IA-64. A bi-endian kifejezés a hardverre nézve azt jelenti, hogy számítások végzésekor vagy adattovábbításkor a két lehetőség közül bármelyiket tudja használni (beállítható, hogy éppen melyikre van szükség). A legtöbb architektúra szoftveresen kapcsolható át a kiválasztott bájtsorrend módra/formára (többnyire a gép indításakor); bár léteznek olyan architektúrák amelyeknél az alapértelmezett bájtsorrendet hardveresen állítják be (alaplapon), így szoftveresen nem is lehet átkapcsolni (például a DEC Alpha, amelyik „nagy az elején” módban működik a Cray T3E-ben).

Középső az elején – middle-endianness

Bizonyos architektúrák, amelyeket középső az elején vagy middle-endian-nak neveznek (vagy néha kevert bájtsorrend vagy mixed-endian), az előzőeknél sokkal bonyolultabb tárolási módot használnak.

Ennek bemutatásához ismét a megszokott példához fordulunk: tegyük fel, hogy a 32 bites értéket most szószervezésű (egy szó 2 bájt) egység mellett kell tárolni a memóriában. Ez a memória 2 bájtos elemi egységeket képes kezelni, a 2 bájtonkénti címnövekedés pedig 1.

100 101 … 4A 3B 2C 1D … vagy egy másik lehetőség:

100 101 … 2C 1D 4A 3B …

A fenti példával kapcsolatosan két megjegyzést kell tenni: az első példa a „nagy az elején” szerinti lehetséges megoldást mutatja, míg a másik a „kicsi az elején” szerintit. A valódi megoldások ennél bonyolultabbak, ugyanis a bájtok cseréjére sokkal több lehetőség van.

Az a formátum, amiben a VAX és az ARM processzorok a kétszeres pontosságú lebegőpontos számokat tárolják, kevert bájtsorrendű. A 32 bites szavak „középső az elején” formátumban tárolódnak a PDP-11-ben, ezért használják a pdp-endian kifejezést is, ha erre a formátumra akarnak utalni.

A bájtsorrend bit szintű értelmezése A bájtsorrend koncepció kevéssé fontos a bitek bájtban elfoglalt helyét illetően, mivel az architektúrák általában nem támogatják egyes bitek bájton belüli direkt címzését. A bájton belüli bitek, bitcsoportok címzése helyett a logikai műveletek adnak jól definiált eredményeket, így mondhatjuk, hogy a bitek szempontjából az architektúrák bájtsorrend függetlenek.

Sajnos azonban a bájtszintű „bájtsorrend” mégiscsak okozhat problémákat: ha a tárolandó bit sorozat nem pontosan egy bájt hosszúságú, akkor az egy bájt tárolásával kapcsolatos bájtsorrend megfontolások mégsem hagyhatók figyelmen kívül. Egy tárolt bájt legszignifikánsabb bitjének az értelmezése elvezet a bit szintű „bájtsorrend” kérdéseihez. Tovább bonyolítja a helyzetet, hogy egyes programnyelvek, például a C megengedi a rekord adatszerkezetben a bitmező használatát. Ebben az esetben már fel kell tételeznünk bit szintű „bájtsorrendet” (szerencsére ez nem architektúra szinten, hanem fordítóprogram szinten jelentkezik, azonban a hordozhatóság szempontjából egyáltalán nem elhanyagolható).

Ha egy file beolvasása a memóriából rekordonként történik, vagy az írása úgy történik, mint egy bitekből álló nagy blokk, akkor felmerül a lehetősége annak, hogy a rekord mezői nem lesznek megfelelő bájt sorrendűek. Különböző eljáráshívásokkal megvalósított konverziókkal lehet biztosítani, hogy a rekordok bájtszintű „bájtsorrendje” megfelelő legyen. Hasonló meggondolásokat kell tenni, ha a fent említett rekordokat hálózaton keresztül adatcsomagokban továbbítják. Ekkor ugyanis lehetséges, hogy a bitcsoportok határai nem esnek egybe byte határokkal, így a küldött csomagok értelmezése szinte megjósolhatatlan lehet.

Hordozhatósági problémák A bájtsorrend alapvetően érinti a szoftverek hordozhatóságát. Például, egy bináris formában tárolt adat értelmezése egy megfelelő bitmaszk használatával feltétlenül érintett a bájtsorrend szempontjából, mivel a különböző bájtsorrend szerint tárolt adatok más és más eredményeket adnak, a maszk értékétől függetlenül.

Egy program által, közös formátumba felírt bináris adatok ugyancsak érintettek lehetnek: például ha az adatokat a BMP bitmap formátumban kell felírni, („elől a kicsi” egészek), és ha az adat tárolása „elől a nagy” megoldású, akkor az adatok sérülhetnek, és nem illeszthetők az adott formátumhoz.

Azoknak a szoftvereknek, amelyeknek információkat kell megosztaniuk különböző eltérő bájtsorrendű hálózati csomópontok között, általában két lehetséges stratégia közül választhatnak. Vagy kiválasztanak egy adott bájtsorrendet és csak azt használják, vagy valamilyen formában közlik, hogy milyen bájtsorrend az adott adat. Az adott bájtsorrend kezelését mindkét esetben a fogadónak kell megoldania. Mindkét közelítési módnak vannak előnyei. Egyfelől csak egyféle bájtsorrendet kell dekódolni, másfelől, a többféle bájtsorrend megengedése lehetővé teszi, hogy az adott architektúra – szoftveres támogatás nélkül – képes kezelni az adatokat (ez hatékonyság növekedését jelenthet). A legtöbb Internet szabvány az első megközelítést alkalmazza: meghatározza, hogy a „nagy az elején” bájtsorrend a kötelező. Több szállító azt a bájtsorrendet használja, amit az adott platform biztosít, és vannak alkalmazások, mint például az X11, amelyek a második megközelítést alkalmazzák.

Az UTF-16 kódokat írhatjuk akár „nagy az elején” vagy „kicsi az elején” sorrend szerint. Az ábrázolási mód megengedi az ún. bájtsorrend jelzést (Byte Order Mark – BOM) egy 2 bájtos string, ami jelzi a használt bájtsorrendet. Hasonló 4 bájtos bájtsorrend jelzést használ a ritkán alkalmazott UTF-32.

Programozási példa a probléma bemutatására A következő, C nyelven írt alkalmazás jól mutatja, hogy milyen veszélyeket rejt az eltérő bájtsorrend: #include <stdio.h> #include <string.h>

int main(void) { FILE *fp;

/* Adatstruktura a peldahoz*/ struct { char one; int two; char three; } data;

/* Az adatstruktura adatokkal valo feltoltese */ strcpy(data.one, "foo"); data.two = 0x01234567; strcpy(data.three, "bar");

/* Iras a file-ba */ fp = fopen("output", "wb"); if (fp != NULL) { fwrite(&data, sizeof data, 1, fp); fclose(fp);