Little Endian vs Big Endian in C

Little Endian vs Big Endian in C

In questo tutorial, discuteremo del concetto di endianness nel computer. Endian significa ordinare il byte. Al computer sono presenti due tipi di endianness: Big Indian e Little Indian. Quando i dati vengono archiviati in memoria, i bit vengono archiviati byte per byte in byte. Il byte è un'unità di dati di memoria che consiste in un gruppo di 8 bit. La memoria del computer è indirizzabile al byte, quindi solo un byte può essere presente all'interno della posizione della memoria. Quando i dati sono solo un byte, questo byte viene archiviato in una singola posizione di memoria. Ma quando i dati sono più di un byte, questi byte possono essere memorizzati in posizione di memoria in due modi diversi.

Esempi da capire:

int x = 513;

La rappresentazione binaria a due byte di 513 è 0000001000000001.

MSB LSB
00000010 00000001

La memoria è indirizzabile al byte. Un byte è archiviato in una posizione di memoria e questa posizione di memoria ha un indirizzo. Se un byte viene archiviato nell'indirizzo "A", il byte successivo viene archiviato nell'indirizzo successivo che è "A+1", e così via. Ora, i byte possono essere archiviati nella memoria dai byte più sinistra ai byte più destra o dai byte più destra ai byte più sinistra.

Qui, l'indirizzo di memoria iniziale è "A". Quindi, se i byte sono archiviati nella memoria dai byte più sinistra ai byte più a destra, il byte più sinistro "00000010"È memorizzato nella posizione di memoria" A "e il byte più a destra"00000001"È memorizzato nella posizione della memoria" A+1 ".

a - 1
UN 00000010
A + 1 00000001
A + 2

Cos'è Big Endian?

Quando il byte più significativo è presente nella posizione di memoria più piccola, il byte successivo viene archiviato nell'indirizzo di memoria successivo e così via. Questo tipo di ordine di byte si chiama "Big Endian".

Se i byte sono archiviati nella memoria dai byte più destra ai byte più a sinistra, il byte più destro "00000001"È memorizzato nella posizione di memoria" A "e il byte più a sinistra"00000010"È memorizzato nella posizione della memoria" A+1 ".

a - 1
UN 00000001
A + 1 00000010
A + 2

Cos'è Little Endian?

Quando il byte meno significativo viene archiviato nella posizione di memoria più piccola, il byte precedente viene archiviato nell'indirizzo di memoria successivo e così via. Questo tipo di ordine di byte si chiama "Little Endian".

a - 1
UN 00000010
A + 1 00000001
A + 2

Possiamo verificare se un computer è Big Endian o Little Endian usando i seguenti esempi di codice C:

Esempio 1:

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

int main ()
printf ("Machine Endianness =>");
endian ();
restituzione 0;

Produzione:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Esempio1.C -O Esempio1
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Esempio 1
Machine Endianness => Little Endian
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Qui, se l'intero è due byte, la rappresentazione binaria di 1 è 00000000 00000001. Convertiamo il puntatore in un puntatore char che è lungo un byte. Quindi, se accediamo alla prima posizione di memoria e otteniamo il valore di 1, significa che il byte più a destra è archiviato nella posizione di memoria più bassa. È quindi una piccola macchina Endian. Altrimenti, sarà una grande macchina Endian.

Esempio 2:

#includere
Union Endian
int i;
char c [sizeof (int)];
;
int main ()
Union Endian U;
u.i = 1;
se tu.C [0] == 1)
printf ("Little Endian \ n");
altro
printf ("big endian \ n");
restituzione 0;

Produzione:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Esempio2.C -O Esempio2
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Esempio2
Piccolo Endian
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

In questo esempio, usiamo l'unione. Se 1 è conservato nello 0th Posizione dell'array, la macchina deve essere poco endian. Altrimenti, la macchina sarà grande Endian.

Problema nell'endianness

Un computer memorizza e recupera i dati nella stessa endianness in cui il risultato è lo stesso. Il problema sorge in Endianness quando i dati si trasferiscono da una macchina a un'altra macchina. Se le due macchine sono in diverso sesso di byte, significa che un computer utilizza il grande endian e un altro computer utilizza il piccolo endian. Quando i dati si trasferiscono dall'uno all'altro, i problemi effettivi emergono. Questo problema si chiama Nuxi Problema: la stringa "Unix" potrebbe sembrare "Nuxi" su una macchina con un sesso byte diverso.

Un altro problema si presenta quando utilizziamo Typecast nel nostro programma. Ad esempio: se creiamo un array di caratteri di ARR [4] e lo digitiamo a un INT di Byte di dimensioni 4, otterremo risultati diversi su una macchina endian diversa. Discutiamolo nel prossimo esempio.

Esempio 3:

#includere
int main ()

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

Produzione:

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

In questo esempio, "arr" è un array di caratteri. Lo digitiamo su un numero intero a 4 byte x. Se compiliamo il programma in una piccola macchina Endian, otteniamo il valore di 0x00000001. Ma se compiliamo il programma in una grande macchina Endian, otteniamo il valore di 0x01000000.

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

Esempio 4:

#includere
int main ()

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

Produzione:

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

Questo esempio è lo stesso dell'esempio 3. Cambia solo il valore per capirlo in modo più semplice. Se compiliamo il programma in una piccola macchina Endian, otteniamo il valore di 0x01000000. Ma se compiliamo il programma in una grande macchina Endian, otteniamo il valore di 0x00000001.

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

Quando i dati vengono trasferiti da una macchina endian a un'altra macchina endian, dobbiamo scambiare i dati di conseguenza. Ora, vediamo come scambiare i dati nei seguenti esempi.

Esempio 5:

In questo esempio, utilizziamo l'operazione bitwise per scambiare i dati. Nell'operazione bitwise, non vi è alcun effetto di endianness.

#includere
#includere
uint32_t byteswap (valore uint32_t)

Uint32_t risultato = 0;
risultato = risultato | (Valore e 0x000000ff) << 24;
risultato = risultato | (Valore e 0x0000ff00) << 8;
risultato = risultato | (valore & 0x00ff0000) >> 8;
risultato = risultato | (valore & 0xFF000000) >> 24;
risultato di ritorno;

int main ()

uint32_t data = 0x44445555;
uint32_t resultData = 0;
resultData = bytesWap (dati);
printf ("dati originali => 0x%x \ n", dati);
printf ("dati convertiti => 0x%x \ n", resultData);
restituzione 0;

Produzione:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Esempio3.C -o Esempio3
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Esempio3
Dati originali => 0x44445555
Dati convertiti => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Esempio 6:

In questo esempio, faremo la stessa cosa che abbiamo fatto nell'esempio 5. Ma qui, usiamo le macro invece della funzione.

#includere
#includere
#define Change_Endianness (a) ((((Uint32_t) (A) e 0xFF000000) >> 24) \

| (((uint32_t) (a) e 0x00ff0000) >> 8) \
| (((uint32_t) (a) e 0x0000ff00) << 8) \
| (((uint32_t) (a) e 0x000000ff) << 24))
int main ()
uint32_t data = 0x44445555;
uint32_t resultData = 0;
resultData = Change_Endianness (dati);
printf ("dati originali => 0x%x \ n", dati);
printf ("dati convertiti => 0x%x \ n", resultData);
restituzione 0;

Produzione:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Esempio6.C -O Esempio6
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Esempio6
Dati originali => 0x44445555
Dati convertiti => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Esempio 7:

In questo esempio, faremo la stessa cosa che abbiamo fatto nell'esempio precedente. Ma qui, usiamo l'unione.

#includere
#includere
TypeDef Union

uint32_t rawdata;
uint8_t DataBuff [4];
Rawdata;
uint32_t Change_Endianness (valore uint32_t)

Cambio di rawdata, originali;
Originale.u32rawdata = value;
// Modifica il valore
Modifica.DataBuff [0] = originale.DataBuff [3];
Modifica.DataBuff [1] = originale.DataBuff [2];
Modifica.DataBuff [2] = originale.DataBuff [1];
Modifica.DataBuff [3] = originale.DataBuff [0];
restituzione (cambiamento.Rawdata);

int main ()
uint32_t data = 0x44445555;
uint32_t resultData = 0;
resultData = Change_Endianness (dati);
printf ("dati originali => 0x%x \ n", dati);
printf ("dati convertiti => 0x%x \ n", resultData);
restituzione 0;

Produzione:

somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ gcc Esempio5.C -o Esempio5
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $ ./Esempio5
Dati originali => 0x44445555
Dati convertiti => 0x55554444
somnath@somnath-virtualbox: ~/desktop/c_prog/endian $

Quando inviamo i dati sulla rete, i dati vengono inviati in un formato comune. Quando i dati vengono inviati sulla rete, non conosciamo l'endianness del mittente e del ricevitore. Quindi, usiamo un ordine speciale che è grande Endian. Questo ordine si chiama "ordine di rete".

Se il mittente è una piccola macchina Endian, converte i dati in un grande ordine di Endian prima di inviare i dati. Se il ricevitore è una piccola macchina Endian, converte i dati in un piccolo formato Endian dopo aver ricevuto i dati.

Quando inviamo i dati alla rete, vengono utilizzate le seguenti macro:

Htons () - "Host to Network Short"

Htonl () - "Host to Network Long"

NTOHS () - "Network to Hoster Short"

ntohl () - "rete per ospitare a lungo"

htons () - Questa macro viene letta come "host to network short". I byte di un valore non firmato a 16 bit dovrebbero essere riorganizzati come i seguenti:

Ordine del processore -> Ordine di rete.

Htonl () - Questa macro viene letta come "host per fare rete". I byte di un valore non firmato a 32 bit devono essere riorganizzati come i seguenti:

Ordine del processore -> Ordine di rete.

ntohs () - Questa macro viene letto come "rete per ospitare". I byte di un valore non firmato a 16 bit dovrebbero essere riorganizzati come i seguenti:

Ordine di rete -> Ordine del processore.

ntohl () - Questa macro viene letto come "rete per ospitare a lungo". I byte di un valore non firmato a 32 bit devono essere riorganizzati come i seguenti:

Ordine di rete -> Ordine del processore.

Conclusione

In questo tutorial, abbiamo imparato i dettagli sull'entennità nel computer. Sembra che l'utilizzo di un approccio di endianness sull'altro non abbia alcun vantaggio. Sono entrambi ancora utilizzati da varie architetture. La maggior parte dei personal computer e dei laptop oggi impiegano le CPU (e i loro cloni) a base di poca endiri), rendendo il piccolo endian come architettura predominante per i computer desktop.