Little Endian gegen Big Endian in C

Little Endian gegen Big Endian in C

In diesem Tutorial diskutieren wir das Konzept der Endiantheit im Computer. Endian bedeutet Byte -Bestellung. Zwei Arten von Endianess sind auf dem Computer vorhanden: Big Indian und Little Indianer. Wenn die Daten im Speicher gespeichert sind, werden die Bits byte-by-byte im Byte gespeichert. Byte ist eine Einheit von Speicherdaten, die aus einer Gruppe von 8 Bit besteht. Der Computerspeicher ist byteadressiv. Wenn die Daten nur ein Byte sind, wird dieses Byte an einem einzigen Speicherort gespeichert. Wenn die Daten jedoch mehr als ein Byte sind, können diese Bytes auf zwei verschiedene Arten an Speicherort gespeichert werden.

Beispiele zu verstehen:

int x = 513;

Zwei Byte -binäre Darstellung von 513 ist 0000001000000001.

MSB LSB
00000010 00000001

Speicher ist Byte adressierbar. Ein Byte wird an einem Speicherort gespeichert und dieser Speicherort hat eine Adresse. Wenn ein Byte in der Adresse „A“ gespeichert ist, wird das nächste Byte in der nächsten Adresse gespeichert, die „A+1“ ist, und so weiter. Jetzt können die Bytes im Speicher von den linken Bytes bis hin zu den rechtssten Bytes oder von den rechtssten Bytes bis zu den linken Bytes gespeichert werden.

Hier lautet die Startspeicheradresse "A". Also, wenn die Bytes von den linken Bytes bis hin zu den rechtsem Bytes, dem linken Byte, im Speicher gespeichert werden00000010"Wird im Speicherort" A "und im rechtsten Byte gespeichert"00000001"Wird im Speicherort" a+1 "gespeichert.

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

Was ist großer Endianer?

Wenn das bedeutendste Byte am kleinsten Speicherort vorhanden ist, wird das nächste Byte in der nächsten Speicheradresse und so weiter gespeichert. Diese Art von Byte -Ordnung heißt "Big Endian".

Wenn die Bytes im Speicher von den rechtssten Bytes bis zu den linken Bytes gespeichert sind, ist das rechte Byte. “00000001"Wird am Speicherort" A "und im links am meisten" gespeichert "00000010"Wird im Speicherort" a+1 "gespeichert.

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

Was ist kleiner Endianer?

Wenn das am wenigsten signifikante Byte am kleinsten Speicherort gespeichert wird, wird das vorherige Byte in der nächsten Speicheradresse und so weiter gespeichert. Diese Art von Byte -Reihenfolge heißt "Little Endian".

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

Wir können überprüfen, ob ein Computer mit den folgenden C -Code -Beispielen ein großer Endianer oder Little Endian ist:

Beispiel 1:

#enthalten
void endian ()
int x = 1;
char *a = (char *) & x;
if (a [0] == 1)
printf ("Little Endian \ n");
anders
printf ("Big Endian \ n");

int main ()
printf ("machine Endiangness =>");
Endian ();
Rückkehr 0;

Ausgang:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Beispiel1.C -o Beispiel1
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Beispiel 1
Machine Endiangness => Little Endian
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Wenn die Ganzzahl zwei Bytes ist, ist die binäre Darstellung von 1 00000000 00000001. Wir konvertieren den Zeiger in einen Zeichenzeiger, der ein Byte lang ist. Wenn wir also auf den ersten Speicherort zugreifen und den Wert von 1 erhalten, bedeutet dies, dass das rechtste Byte am niedrigsten Speicherort gespeichert ist. Es ist dann eine kleine endianische Maschine. Andernfalls ist es eine große endianische Maschine.

Beispiel 2:

#enthalten
Union Endian
int i;
char c [sizeof (int)];
;
int main ()
Union Endian u;
u.i = 1;
wenn du.c [0] == 1)
printf ("Little Endian \ n");
anders
printf ("Big Endian \ n");
Rückkehr 0;

Ausgang:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Beispiel2.C -o Beispiel2
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Beispiel2
Kleiner Endian
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

In diesem Beispiel verwenden wir Union. Wenn 1 in der 0 gespeichert istth Ort des Arrays muss die Maschine wenig Endian sein. Andernfalls ist die Maschine großer Endianer.

Problem in der Endiangigkeit

Ein Computer speichert und ruft die Daten in derselben Endianess ab, in der das Ergebnis das gleiche ist. Das Problem tritt in Endianges auf, wenn die Daten von einer Maschine auf eine andere Maschine übertragen werden. Wenn sich die beiden Maschinen in verschiedenen Byte -Sex befinden, bedeutet dies, dass ein Computer den großen Endian verwendet und ein anderer Computer den kleinen Endian verwendet. Wenn die Daten von einem zum anderen übertragen werden, treten die tatsächlichen Probleme auf. Dieses Problem heißt Nuxi -Problem: Die Zeichenfolge „Unix“ könnte auf einer Maschine mit einem anderen Byte -Sex wie „Nuxi“ aussehen.

Ein weiteres Problem tritt auf, wenn wir typecast in unserem Programm verwenden. Zum Beispiel: Wenn wir ein Zeichenarray von ARR [4] erstellen und es auf ein INT von Größe 4 -Byte typern, erhalten wir ein anderes Ergebnis auf verschiedenen Endian Machine. Lassen Sie uns es im nächsten Beispiel diskutieren.

Beispiel 3:

#enthalten
int main ()

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

Ausgang:

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

In diesem Beispiel ist „arr“ ein Charakter -Array. Wir typern es zu einer 4 -Byte -Ganzzahl x. Wenn wir das Programm in einer kleinen endianischen Maschine kompilieren, erhalten wir den Wert von 0x00000001. Wenn wir das Programm jedoch in einer Big Endian -Maschine zusammenstellen, erhalten wir den Wert von 0x01000000.

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

Beispiel 4:

#enthalten
int main ()

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

Ausgang:

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

Dieses Beispiel ist das gleiche wie in Beispiel 3. Ändern Sie nur den Wert, um ihn auf einfachere Weise zu verstehen. Wenn wir das Programm in einer kleinen endianischen Maschine kompilieren, erhalten wir den Wert von 0x01000000. Wenn wir das Programm jedoch in einer Big Endian -Maschine zusammenstellen, erhalten wir den Wert von 0x00000001.

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

Wenn die Daten von einer Endian -Maschine auf eine andere Endian -Maschine übertragen werden, müssen wir die Daten entsprechend tauschen. Lassen Sie uns nun sehen, wie Sie die Daten in den folgenden Beispielen austauschen können.

Beispiel 5:

In diesem Beispiel verwenden wir den bitweisen Betrieb, um die Daten auszutauschen. Beim bitimen Betrieb gibt es keine Auswirkung der Endiantheit.

#enthalten
#enthalten
uint32_t byteswap (uint32_t Wert)

uint32_t result = 0;
Ergebnis = Ergebnis | (Wert & 0x000000ff) << 24;
Ergebnis = Ergebnis | (Wert & 0x0000ff00) << 8;
Ergebnis = Ergebnis | (Wert & 0x00ff0000) >> 8;
Ergebnis = Ergebnis | (Wert & 0xff000000) >> 24;
Rückgabeergebnis;

int main ()

uint32_t data = 0x44445555;
uint32_t resultdata = 0;
resultdata = byteswap (Daten);
printf ("Originaldaten => 0x%x \ n", Daten);
printf ("konvertierte Daten => 0x%x \ n", resultdata);
Rückkehr 0;

Ausgang:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Beispiel3.C -o Beispiel3
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Beispiel3
Originaldaten => 0x44445555
Konvertierte Daten => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Beispiel 6:

In diesem Beispiel werden wir das Gleiche tun wie in Beispiel 5. Aber hier verwenden wir Makros anstelle von Funktionen.

#enthalten
#enthalten
#define change_endiangness (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 resultdata = 0;
resultdata = change_endiangess (Daten);
printf ("Originaldaten => 0x%x \ n", Daten);
printf ("konvertierte Daten => 0x%x \ n", resultdata);
Rückkehr 0;

Ausgang:

somnath@somnath-virtualBox: ~/desktop/c_prog/endian $ gcc Beispiel6.C -o Beispiel6
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Beispiel6
Originaldaten => 0x44445555
Konvertierte Daten => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Beispiel 7:

In diesem Beispiel werden wir das Gleiche tun wie im vorherigen Beispiel. Aber hier benutzen wir Union.

#enthalten
#enthalten
Typedef Union

uint32_t rawdata;
UINT8_T -DatenAbuff [4];
Rohdaten;
uint32_t change_endiangness (uint32_t Wert)

Rawdata -Veränderung, Orginal;
Orginal.U32RAWDATA = Wert;
// den Wert ändern
Ändern.Datenpuff [0] = Orginal.Datenpuff [3];
Ändern.Datenpuff [1] = Orginal.Datenpuff [2];
Ändern.Datenpuff [2] = Orginal.Datenpuff [1];
Ändern.Datenpuff [3] = Orginal.Datenpuff [0];
Rückgabe (Veränderung.Rohdaten);

int main ()
uint32_t data = 0x44445555;
uint32_t resultdata = 0;
resultdata = change_endiangess (Daten);
printf ("Originaldaten => 0x%x \ n", Daten);
printf ("konvertierte Daten => 0x%x \ n", resultdata);
Rückkehr 0;

Ausgang:

somnath@somnath-virtualBox: ~/Desktop/c_prog/endian $ gcc Beispiel5.C -o Beispiel5
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Beispiel5
Originaldaten => 0x44445555
Konvertierte Daten => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Wenn wir die Daten über das Netzwerk senden, werden die Daten in einem gemeinsamen Format gesendet. Wenn Daten über das Netzwerk gesendet werden, kennen wir nicht die Endanging des Absenders und des Empfängers. Wir verwenden also eine Sonderbestellung, die Big Endian ist. Diese Reihenfolge wird als "Netzwerkreihenfolge" bezeichnet.

Wenn der Absender eine kleine endianische Maschine ist, wandelt er die Daten in eine große endianische Bestellung um, bevor er die Daten sendet. Wenn der Empfänger eine kleine endianische Maschine ist, wandelt er die Daten nach Empfangen der Daten in ein kleines Endian -Format um.

Wenn wir die Daten an das Netzwerk senden, werden folgende Makros verwendet:

htons () - "Host to Network Short"

Htonl () - "Host to Network Long"

NTOHS () - "Netzwerk zum Host Short"

NTOHL () - "Netzwerk zu Host Long"

htons () - Dieses Makro wird als "Host to Network Short" gelesen. Ein Bytes eines 16-Bit-Wertschöpfungswerts sollte wie folgt neu angeordnet werden:

Prozessorreihenfolge -> Netzwerkreihenfolge.

htonl () - Dieses Makro wird als "Host to Network Long" gelesen. Ein 32-Bit-Bytes des nicht signierten Wertes sollte wie folgt neu angeordnet werden:

Prozessorreihenfolge -> Netzwerkreihenfolge.

ntohs () - Dieses Makro wird als "Netzwerk zum Hosting Short" gelesen. Ein Bytes eines 16-Bit-Wertschöpfungswerts sollte wie folgt neu angeordnet werden:

Netzwerkreihenfolge -> Prozessorreihenfolge.

ntohl () - Dieses Makro wird als "Netzwerk zu Host Long" gelesen. Ein 32-Bit-Bytes des nicht signierten Wertes sollte wie folgt neu angeordnet werden:

Netzwerkreihenfolge -> Prozessorreihenfolge.

Abschluss

In diesem Tutorial haben wir die Details über Endianess im Computer gelernt. Es scheint, dass die Verwendung eines Endianges -Ansatzes gegenüber dem anderen keinen Vorteil hat. Sie werden beide immer noch von verschiedenen Architekturen genutzt. Die Mehrheit der Personalcomputer und Laptops verwenden heute den Little-Endian-basierten CPUs (und ihre Klone), wodurch der kleine Endian als vorherrschende Architektur für Desktop-Computer ist.