niedziela, 10 czerwca 2018

C - Little oraz Big Endian

W tym poście chciałbym opisać sposoby zapisywania danych w pamięci.

[Źródło: https://icons8.com/icon/40670/c-programming]


Big Endian:


W tym przypadku najbardziej znaczący bajt umieszczany jest jako pierwszy. Czyli liczba 0x12345678 zostanie zapisana tak:

0x12 | 0x34 | 0x56 | 0x78

Little Endian:


Tutaj najbardziej znaczący bajt zostanie umieszczony jako ostatni. Co oznacza, że liczba z przykładu wcześniejszego zostanie przedstawiona jako:

0x78 | 0x56 | 0x34 | 0x12

W większości przypadków sposób zapisu danych nie ma aż tak wielkiego znaczenia. Ponieważ kompilator zajmie się odpowiednim zaprezentowaniem danych. 

Zmiana formatu danych musi zostać wykonana przy przekazywaniu ramki danych dla TCP. Przykładowe makra odwracające kolejność wyglądają następująco:

  1. #define CONVER_16BITDATA(valueToChange)     ((((valueToChange)>>8)&0xff)|(((valueToChange)<<8)&0xff00))
  2. #define CONVER_32BITDATA(valueToChange)     ((((valueToChange)>>24)&0xff)|(((valueToChange)>>8)&0xff00)|(((valueToChange<<8)&0xff0000)| (((valueToChange)<<24)&0xff000000))

Zadaniem powyższych makr jest zamiana kolejności bajtów w zmiennej 16 lub 32 bitowej.

Aby sprawdzić w jakim formacie zapisywane są zmienne w danej maszynie można posłużyć się poniższym programem:

  1. #include <stdio.h>
  2. #include <stdint.h>
  3.  
  4. int main()
  5. {
  6.    uint32_t checkValue = 0x01234567;
  7.    
  8.    uint8_t *pointer = (char*)&checkValue;
  9.    
  10.    if (*pointer == 0x67)
  11.    {
  12.        printf("LitleEndian");
  13.    }
  14.    else
  15.    {
  16.        printf("BigEndian");
  17.    }
  18.    
  19.    return 0;
  20. }

Tutaj wprowadzamy wartość do pamięci a następnie tworzymy wskaźnik do jednego bajtu pamięci. Oznacza to, że jeśli wskaźnik wskaże wartość 0x67, czyli najmniej istotny bajt danych, to zapis odbywa się za pomocą Little Endian. W innym przypadku maszyna obsługuje Big Endian.