Little Endian vs Big Endian i C

Little Endian vs Big Endian i C

I denne opplæringen vil vi diskutere begrepet endianshet i datamaskinen. Endian betyr byte bestilling. To typer endianness er til stede i datamaskinen: stor indisk og liten indisk. Når dataene er lagret i minnet, lagres bitene byte-by-byte i byte. Byte er en enhet med minnedata som består av en gruppe på 8 biter. Datamaskinminnet er byteadresserbar, så bare en byte kan være til stede på minneplassen. Når dataene bare er en byte, lagres denne byten på et enkelt minneplassering. Men når dataene er mer enn en byte, kan disse byte lagres på minneplassering på to forskjellige måter.

Eksempler å forstå:

int x = 513;

To byte binærrepresentasjon av 513 er 0000001000000001 00000000001.

MSB LSB
00000010 00000001

Minnet er byte adresserbart. En byte lagres på ett minneplass, og dette minneplassen har en adresse. Hvis en byte er lagret i adressen “A”, lagres neste byte i neste adresse som er “A+1”, og så videre. Nå kan bytene lagres i minnet fra venstre byte til de høyre byte eller fra de høyre byte til venstre byte.

Her er startminneadressen “A”. Så hvis bytene er lagret i minnet fra venstre byte til de høyre byte, er venstre byte "00000010”Lagres på minnestedet“ A ”og den høyre byte”00000001”Lagres på minneplassen“ A+1 ”.

A - 1
en 00000010
A + 1 00000001
A + 2

Hva er stor endian?

Når den mest betydningsfulle byten er til stede på det minste minneplassen, lagres neste byte i neste minneadresse, og så videre. Denne typen byteordre kalles “Big Endian”.

Hvis bytene er lagret i minnet fra de høyre byte til venstre byte, er den høyre mest byte “00000001”Lagres på minnestedet“ A ”og den venstre byte”00000010”Lagres på minneplassen“ A+1 ”.

A - 1
en 00000001
A + 1 00000010
A + 2

Hva er lite Endian?

Når den minst betydningsfulle byten lagres på det minste minneplassen, lagres den forrige byten i neste minneadresse, og så videre. Denne typen byteordre kalles “Little Endian”.

A - 1
en 00000010
A + 1 00000001
A + 2

Vi kan sjekke om en datamaskin er stor Endian eller Little Endian ved å bruke følgende C -kodeeksempler:

Eksempel 1:

#inkludere
void endian ()
int x = 1;
char *a = (char *) & x;
if (a [0] == 1)
printf ("liten endian \ n");
ellers
printf ("big endian \ n");

int main ()
printf ("Machine EndiNness =>");
endian ();
retur 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel1.C -o Eksempel1
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel1
Maskinendiansness => liten endian
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Her, hvis heltallet er to byte, er den binære representasjonen av 1 00000000 00000001. Vi konverterer pekeren til en røyepeker som er en byte lang. Så hvis vi får tilgang til det første minnestedet og vi får verdien 1, betyr det at den høyre byte er lagret på det laveste minneplassen. Det er da en liten endian maskin. Ellers vil det være en stor endian maskin.

Eksempel 2:

#inkludere
Union Endian
int jeg;
char c [sizeof (int)];
;
int main ()
Union Endian U;
u.i = 1;
hvis du.C [0] == 1)
printf ("liten endian \ n");
ellers
printf ("big endian \ n");
return 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel2.C -o Eksempel2
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel2
Lille endian
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

I dette eksemplet bruker vi Union. Hvis 1 er lagret i 0th Plasseringen av matrisen, må maskinen være liten endian. Ellers vil maskinen være stor endian.

Problem i endianness

En datamaskin lagrer og henter dataene i samme endiannitet som resultatet er det samme. Problemet oppstår i endiansness når dataene overfører fra en maskin til en annen maskin. Hvis de to maskinene er i forskjellig byte -sex, betyr det at en datamaskin bruker den store endianen og en annen datamaskin bruker den lille endianen. Når dataene overfører fra hverandre, kommer de faktiske problemene opp. Dette problemet kalles Nuxi -problem: "Unix" -strengen kan se ut som "Nuxi" på en maskin med en annen byte -sex.

Et annet problem dukker opp når vi bruker typecast i programmet vårt. For eksempel: Hvis vi oppretter en karakterutvalg av ARR [4] og typecast det til en int av størrelse 4 byte, vil vi få et annet resultat på forskjellige endianmaskiner. La oss diskutere det i neste eksempel.

Eksempel 3:

#inkludere
int main ()

char arr [4] = 0x01, 0x00,0x00,0x00;
int x = *(int *) arr;
printf ("0x%x \ n", x);
return 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel3.C -o Eksempel3
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel3
0x1
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

I dette eksemplet er “ARR” en karaktergruppe. Vi skriver det til et 4 byte heltall x. Hvis vi kompilerer programmet i en liten endian maskin, får vi verdien 0x00000001. Men hvis vi sammenstiller programmet i en stor endian maskin, får vi verdien 0x01000000.

0x01 0x00 0x00 0x00
arr [0] arr [1] arr [2] arr [3]

Eksempel 4:

#inkludere
int main ()

char arr [4] = 0x00, 0x00,0x00,0x01;
int x = *(int *) arr;
printf ("0x%x \ n", x);
retur 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel4.C -o Eksempel4
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel4
0x1000000
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Dette eksemplet er det samme som i eksempel 3. Bare endre verdien for å forstå den på enklere måte. Hvis vi kompilerer programmet i en liten endian maskin, får vi verdien 0x01000000. Men hvis vi sammenstiller programmet i en stor endian maskin, får vi verdien 0x00000001.

0x00 0x00 0x00 0x01
arr [0] arr [1] arr [2] arr [3]

Når dataene overføres fra en endianmaskin til en annen Endian -maskin, må vi bytte data deretter. La oss nå se hvordan du kan bytte dataene i følgende eksempler.

Eksempel 5:

I dette eksemplet bruker vi bitvis operasjon for å bytte data. I bitvis drift er det ingen effekt av endiansness.

#inkludere
#inkludere
uint32_t byteswap (uint32_t verdi)

uint32_t resultat = 0;
Resultat = resultat | (Verdi & 0x000000ff) << 24;
Resultat = resultat | (Verdi & 0x0000ff00) << 8;
Resultat = resultat | (verdi & 0x00ff0000) >> 8;
Resultat = resultat | (verdi & 0xff000000) >> 24;
returresultat;

int main ()

uint32_t data = 0x44445555;
uint32_t resultatdata = 0;
resultatdata = byteswap (data);
printf ("original data => 0x%x \ n", data);
printf ("konverterte data => 0x%x \ n", resultatdata);
retur 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel3.C -o Eksempel3
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel3
Originaldata => 0x44445555
Konverterte data => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Eksempel 6:

I dette eksemplet vil vi gjøre det samme som vi gjorde i eksempel 5. Men her bruker vi makroer i stedet for funksjon.

#inkludere
#inkludere
#Define Change_endiantness (a) ((((uint32_t) (a) & 0xff000000) >> 24) \

| (((uint32_t) (a) & 0x00ff0000) >> 8) \
| (((uint32_t) (a) & 0x0000ff00) << 8) \
| (((uint32_t) (a) & 0x000000ff) << 24))
int main ()
uint32_t data = 0x44445555;
uint32_t resultatdata = 0;
ResultatData = Change_endiantness (data);
printf ("original data => 0x%x \ n", data);
printf ("konverterte data => 0x%x \ n", resultatdata);
retur 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel6.C -o Eksempel6
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel6
Originaldata => 0x44445555
Konverterte data => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Eksempel 7:

I dette eksemplet vil vi gjøre det samme som vi gjorde i forrige eksempel. Men her bruker vi Union.

#inkludere
#inkludere
typedef union

uint32_t rawdata;
uint8_t databuff [4];
Rådata;
uint32_t endring_endiansness (uint32_t verdi)

Rawdata endring, orginal;
Orginal.u32RawData = verdi;
// Endre verdien
Endring.Databuff [0] = orginal.Databuff [3];
Endring.Databuff [1] = orginal.Databuff [2];
Endring.Databuff [2] = orginal.Databuff [1];
Endring.Databuff [3] = orginal.Databuff [0];
Retur (endre.Rådata);

int main ()
uint32_t data = 0x44445555;
uint32_t resultatdata = 0;
ResultatData = Change_endiantness (data);
printf ("original data => 0x%x \ n", data);
printf ("konverterte data => 0x%x \ n", resultatdata);
return 0;

Produksjon:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc eksempel5.C -o Eksempel5
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Eksempel5
Originaldata => 0x44445555
Konverterte data => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Når vi sender dataene over nettverket, sendes dataene i et felles format. Når data blir sendt over nettverket, kjenner vi ikke endianten til avsenderen og mottakeren. Så vi bruker en spesiell ordre som er stor endian. Denne ordren kalles "nettverksrekkefølge".

Hvis avsenderen er en liten endian maskin, konverterer den dataene til en stor endian ordre før du sender dataene. Hvis mottakeren er en liten endian maskin, konverterer den dataene til et lite endianformat etter å ha mottatt dataene.

Når vi sender dataene til nettverket, brukes følgende makroer:

Htons () - “Host to Network Short”

HTONL () - “Vert til nettverk Long”

Ntohs () - “Nettverk for å være vert for kort”

Ntohl () - “Nettverk for å være vert for Long”

htons () - Denne makroen blir lest som "vert for nettverkskort". En 16-bits usignert verdi byte skal omorganiseres som følgende:

Prosessorordre -> Nettverksordre.

Htonl () - Denne makroen blir lest som "vert for nettverk lang". En 32-bits usignert verdi's byte skal omorganiseres som følgende:

Prosessorordre -> Nettverksordre.

ntohs () - Denne makroen blir lest som "nettverk for å være vert for kort". En 16-bits usignert verdi byte skal omorganiseres som følgende:

Nettverksordre -> Prosessorrekkefølge.

ntohl () - Denne makroen blir lest som "nettverk for å være vert for". En 32-bits usignert verdi's byte skal omorganiseres som følgende:

Nettverksordre -> Prosessorrekkefølge.

Konklusjon

I denne opplæringen lærte vi detaljene om endianness i datamaskinen. Det ser ut til at å bruke den ene endianness -tilnærmingen over den andre ikke har noen fordel. De blir begge fortsatt brukt av forskjellige arkitekturer. Flertallet av personlige datamaskiner og bærbare datamaskiner i dag bruker de lite-endian-baserte CPU-ene (og deres kloner), noe som gjør den lille endianen som den dominerende arkitekturen for stasjonære datamaskiner.