Что такое конечность?
- Она относится к тому, как байты наших данных упорядочены в памяти.
- Существует два типа эндианальности, с которыми может работать процессор (технически их три):
- Big Endian
- малый эндиан
- Biendian (исходя из названия, эти типы процессоров могут быть сконфигурированы как любой тип).
- Обратите внимание, что два шестнадцатеричных числа имеют размер в один байт.
Старший значащий бит и Младший значащий бит
Возьмем переменную типа данных int
(т.е. размером 4 байта), имеющую размер 4 байта. размер 4 байта), имеющую значение 0x12345678
, старший значащий бит (MSB) будет 0x1
, а младший значащий бит (LSB) будет 0x8
, аналогично, старший байт будет 0x1234
, а младший байт будет 0x5678
.
В чем разница между Big Endian и Little Endian?
Big Endian
Хранит сначала старший байт, а затем младший, поэтому старший байт занимает младший адрес памяти, а младший байт занимает старший адрес памяти.
Младший эндеец
Сначала хранится младший байт, а затем старший, поэтому младший байт хранится по младшему адресу памяти, а старший — по старшему.
Пример
Рассмотрим шестнадцатеричное значение 0x03E8
:
Обратите внимание, что 0x00
и 0x01
— это адрес байта памяти (поскольку память имеет побайтовую адресацию).
Big Endian Little Endian
+--------+ +--------+
| | | |
0x00| 0x03 | 0x00| 0xE8 |
+--------+ +--------+
| | | |
0x01| 0xE8 | 0x01| 0x03 |
+--------+ +--------+
Почему это важно?
Эндианальность важна, когда два компьютера (процессора) общаются друг с другом, возьмем для примера процессор #A — little-endian, а процессор #B — big-endian, когда процессор #A посылает данные, он пошлет сначала младший байт, а поскольку процессор #B — big-endian, он интерпретирует его как старший байт, таким образом, все данные будут перевернуты.
Как определить тип эндиана вашего процессора?
Обратите внимание, что нам придется выполнить даунскаст указателя, и причина этого в том, что модификатор длины %x
имеет целочисленный тип. Проверьте страницы руководства
Если бы мы не выполняли это преобразование, то результатом было бы одно и то же целое число, независимо от архитектуры нашего процессора.
printf("The size of data type long long is %d.n", sizeof(long long));
printf("The size of data type int is %d.n", sizeof(int));
/* Assign an 8 byte value to x. */
unsigned long long x = 0x0000000000000004;
/*Assign the address of variable x to x_ptr. */
unsigned long long *x_ptr = &x;
/* Both x_ptr and y_ptr have the same value which is the address of variable x.
What are doing here is just telling the processor is variable y_ptr is pointing at an integer, rather than the data type long long.
*/
unsigned int *y_ptr = (unsigned int *)x_ptr;
/* Derefrence the value of y_ptr. */
unsigned int y = *y_ptr;
/* Just printing out the value of y with 0s leading as padding. */
printf("The value of y is %#.8x", y);
Результат будет отличаться в зависимости от архитектуры, значение y будет 0x00000003
, если мы используем процессор с little-endian архитектурой (что мы и делаем, поскольку процессоры x86 являются little-endian), и значение y будет 0x000000
, если мы используем архитектуру big-endian.
Попробуйте этот код
Забавный факт: происхождение названия
Название Big Endian и Little Endian происходит из сатиры Джонатана Свифта «Путешествия Гулливера». В его книге big-endian обозначает человека, который разбивает яйцо с большого конца, а little-endian — того, кто разбивает яйцо с маленького конца.