Endianness a livello di bit

3

Sto imparando l'unione e la struttura e ho scritto il codice qui sotto. Quello che non capisco è perché l'output è diverso quando cambio da un piccolo endian ad un big endian.

La mia comprensione è che endianness è importante quando hai più di un byte. Ma ho solo 8 bit.

Questo codice non è portatile in questo momento e voglio capire come renderlo portatile. Vorrei evitare di rilevare l'endianness o l'utilizzo di tecniche di spostamento dei bit. Conosco le funzioni di htonX ma non penso che si applichi qui.

    #include <stdio.h>

    int main()
    {
      typedef union {
        struct {
          unsigned char b0:1;
          unsigned char b1:1;
          unsigned char b2:1;
          unsigned char b3:1;
          unsigned char b4:1;
          unsigned char b5:1;
          unsigned char b6:1;
          unsigned char b7:1;
        } bits;
        unsigned char byte;
      } HW_Register;

      HW_Register reg;
      reg.byte = 3;

      printf("%d %d %d %d %d %d %d %d\n", 
        reg.bits.b0,
        reg.bits.b1,
        reg.bits.b2,
        reg.bits.b3,
        reg.bits.b4,
        reg.bits.b5,
        reg.bits.b6,
        reg.bits.b7);

      printf("%d\n",reg.byte);
      printf("Size of reg.byte: %d\n", sizeof(reg.byte));
    }
    
posta user2296949 24.07.2015 - 19:58
fonte

1 risposta

5

L'ordine in cui i campi di bit sono posizionati in un numero intero è indipendente dall'ordine in cui i byte sono inseriti in un numero intero. Entrambi sono dettagli di implementazione. Generalmente non è un problema, perché la memoria è solo indirizzabile in byte e tutto l'hardware conserva il valore di un byte durante le trasmissioni.

Tuttavia, mentre l'ordinamento di bit e byte è teoricamente indipendente l'uno dall'altro, le documentazioni della CPU tendono a numerare i bit nello stesso ordine in cui numerano i byte: la documentazione X86 si riferirà al bit meno significativo come bit 0, mentre la documentazione di Power si riferirà al bit più significativo come bit 0. I tuoi scrittori di compilatori sembrano aver scelto la stessa numerazione della rispettiva documentazione.

Come tale, la tua unica speranza di raggiungere la portabilità è di fare un po 'di manovra, definendo una variabile flags e un gruppo di costanti per impostare / mascherare i rispettivi bit:

const unsigned char kBit0 = 1 << 0,
                    kBit1 = 1 << 1,
                    kBit2 = 1 << 2,
                    kBit3 = 1 << 3,
                    kBit4 = 1 << 4,
                    kBit5 = 1 << 5,
                    kBit6 = 1 << 6,
                    kBit7 = 1 << 7,

unsigned char reg = 3;
printf("%d %d %d %d %d %d %d %d\n",
    !!(reg & kBit0),
    !!(reg & kBit1),
    !!(reg & kBit2),
    !!(reg & kBit3),
    !!(reg & kBit4),
    !!(reg & kBit5),
    !!(reg & kBit6),
    !!(reg & kBit7));

Questo numera i bit in modo little endian, indipendentemente dalla macchina. Se si desidera la numerazione big endian, è sufficiente definire le costanti di conseguenza.

    
risposta data 24.07.2015 - 21:05
fonte

Leggi altre domande sui tag