Может кто-нибудь объяснить мне эту функцию «порядка байтов»? - PullRequest
11 голосов
/ 28 марта 2010

Напишите программу, чтобы определить, является ли компьютер прямым или младшим.

bool endianness() {
     int i = 1;
     char *ptr;
     ptr  = (char*) &i;
     return (*ptr);
}

Итак, у меня есть вышеуказанная функция. Я действительно не понимаю. ptr = (char *) & i, что, я думаю, означает указатель на символ по адресу, где я нахожусь, поэтому, если int равен 4 байта, скажем ABCD, мы говорим об A или D, когда вы вызываете char * ? а почему?

Кто-нибудь, пожалуйста, объясните это более подробно? Спасибо.

В частности, ptr = (char *) & i; когда вы приведете его к символу *, какую часть & я получу?

Ответы [ 6 ]

33 голосов
/ 28 марта 2010

Если у вас архитектура с прямым порядком байтов, i будет выглядеть так в памяти (в шестнадцатеричном формате):

01 00 00 00
^

Если у вас архитектура с прямым порядком байтов, i будет выглядеть так в памяти (в шестнадцатеричном формате):

00 00 00 01
^

Приведение к char* дает вам указатель на первый байт целого числа (на которое я указал ^), поэтому значение, на которое указывает char*, будет 01, если вы на архитектуре с прямым порядком байтов и 00, если вы на архитектуре с прямым порядком байтов.

Когда вы возвращаете это значение, 0 преобразуется в false, а 1 преобразуется в true. Итак, если у вас архитектура с прямым порядком байтов, эта функция вернет true, а если у вас архитектура с прямым порядком байтов, она вернет false.

2 голосов
/ 28 марта 2010

Если ptr указывает на байт A или D, это зависит от порядкового номера машины. ptr указывает на тот байт целого числа, который находится на самом низком адресе (остальные байты будут в ptr+1, ...).

На машине с прямым порядком байтов старший значащий байт целого числа (то есть 0x00) будет храниться по этому младшему адресу, поэтому функция вернет ноль.

На машине с прямым порядком байтов все наоборот, младший значащий байт целого числа (0x01) будет храниться по младшему адресу, поэтому функция в этом случае вернет один.

1 голос
/ 28 марта 2010

Используется тип punning для доступа к целому числу в виде массива символов. Если машина имеет старший порядковый номер, это будет старший байт и будет иметь значение ноль, но если машина имеет младший порядок, это будет младший байт, который будет иметь значение один. (Вместо того, чтобы обращаться к i как к одному целому числу, к той же памяти обращаются как к массиву из четырех символов).

0 голосов
/ 03 апреля 2010

Предположим, что int равен 4 байта (в C это не может быть). Это предположение просто для упрощения примера ...

Вы можете посмотреть на каждый из этих 4 байтов в отдельности.

char - это байт, поэтому он смотрит на первый байт 4-байтового буфера.

Если первый байт не равен 0, то это говорит о том, содержится ли младший бит в первом байте.

Я случайно выбрал число 42, чтобы избежать путаницы с каким-либо особым значением в значении 1.

int num = 42;
if(*(char *)&num == 42)
{
      printf("\nLittle-Endian\n");
}
else
{
      printf("Big-Endian\n");
}

Разбивка:

int num = 42; 
//memory of the 4 bytes is either: (where each byte is 0 to 255)
//1) 0 0 0 42
//2) 42 0 0 0

char*p = #/*Cast the int pointer to a char pointer, pointing to the first byte*/
bool firstByteOf4Is42 = *p == 42;/*Checks to make sure the first byte is 1.*/

//Advance to the 2nd byte
++p;
assert(*p == 0);

//Advance to the 3rd byte
++p;
assert(*p == 0);

//Advance to the 4th byte
++p;
bool lastByteOf4Is42 = *p == 42;
assert(firstByteOf4Is42 == !lastByteOf4Is42);

Если firstByteOf4Is42 имеет значение true, у вас есть порядок байтов. Если lastByteOf4Is42 имеет значение true, то у вас есть big-endian.

0 голосов
/ 28 марта 2010

Конечно,

Давайте посмотрим

bool endianness() {
     int i = 1; //This is 0x1:
     char *ptr;
     ptr  = (char*) &i; //pointer to 0001
     return (*ptr);
}

Если для машины задан прямой порядок байтов, то данные будут в * ptr равны 0000 0001.

Если машина имеет Big Endian, то данные будут инвертированы, то есть я буду

i = 0000 0000 0000 0001 0000 0000 0000 0000 

Так что * ptr будет содержать 0x0

Наконец, возвращаемое * ptr эквивалентно

if (*ptr = 0x1 ) //little endian

else //big endian
0 голосов
/ 28 марта 2010

Является ли *((char*)&i) байтом A или байтом D, попадает в суть порядка байтов. В системе с прямым порядком байтов целое число 0x41424344 будет размещено в памяти как: 0x44 43 42 41 (сначала младший байт; в ASCII это "DCBA") В системе с прямым порядком байтов это будет выглядеть так: 0x41 42 43 44. Указатель на это целое число будет содержать адрес первого байта. Рассматривая указатель как целочисленный указатель, вы получаете целое число. Рассмотрите указатель как указатель на символ, и вы получите первый байт, так как это размер символа.

...