2016-12-30 7 views
3

Рассмотрим следующий код:Определение с htons порядок байт

#include <stdio.h> 
#include <arpa/inet.h> 

int main(int argc, char *argv[]) { 
    uint16_t num = 123; 

    if (htons(num) == num) { 
     printf("big endian\n"); 
    } else { 
     printf("little endian\n"); 
    } 
} 

Я задаюсь вопросом, работает ли этот код для проверки порядка байтов? Я видел много вопросов, проверяющих его с помощью различных указателей/char трюков, но я считаю, что это проще. Это исходит из предположения, что если вы конвертируете число в порядок сетевого байта (big endian), если оно совпадает с исходным номером, то вы находитесь в системе с большим энтиром. В противном случае вы находитесь в системе немного endian.

Есть ли ложное предположение в этой проверке? Возможно, сетевой порядок не всегда большой, но it seems it is standardised to be so.

+0

Примечание. У меня нет большой эндианной машины, чтобы проверить этот код, и попытки имитировать такую ​​систему оказываются недружелюбными. –

+0

Если вы хотите быть полностью основательным, предположение состоит в том, что порядок байтов является либо большим, либо бесконечным. Были архитектуры, которые использовали другие байтовые заказы (например, PDP-11 сохранил 32-битное значение 0x01020304 как 0x02 0x01 0x04 0x03). Очевидно, что есть только две возможности для хранения 16-битного значения. –

+0

Реальный вопрос: почему вы вообще заботитесь? 'htons' & friends точно предназначены для того, чтобы пользователь не заботился о endianess. Условия размещения в onm-блоке, основанные на определенной контенте, обычно нарушаются по дизайну. – Olaf

ответ

2

В принципе, C позволяет биты в представлении uint16_t быть в любой реализации определенных целях, а не только «маленький» или «большой младшему». Как написано, ваш тест только говорит вам, что htons переставляет биты 0,1,3,4,5,6 и 2,7-15 отдельно без их смешивания.

Если вы перебираете все мощности двух и находите, что htons(1<<i)==1<<i для i в 0..15, то вы можете заключить, что заказ определенно большой эндиан. Если вы обнаружите, что htons(1<<i)==1<<(i^8) для i в 0..15, вы можете сделать вывод немного endian. В противном случае у вас действительно необычное представление.

На самом деле странных вещей не бывает, и вашего теста должно быть достаточно.

+0

Да, это то осложнение, которое я ожидал, но, как вы указываете, я не ожидал, что это проблема в любой разумной системе. Отличный ответ, спасибо. –

6

Этого достаточно для проверки подлинности во время выполнения.

На больших системах обратного порядка байт, htons (а также ntohs, htonl и ntohl) определяются как не-OPS, в то время как на небольших системах обратного порядка байт они выполняют байты подкачку.

EDIT:

Это также может быть сделано с помощью объединения. Приведенная ниже проверка определяет большой и маленький endian, а также другие более экзотические байтовые порядки.

#include <stdio.h> 
#include <stdint.h> 

union echeck { 
    uint32_t i; 
    char c[4]; 
} echeck = { .c = { 0x01, 0x02, 0x03, 0x04 } }; 

int main() 
{ 
    if (echeck.i == 0x01020304) { 
     printf("big endian\n"); 
    } else if (echeck.i == 0x04030201) { 
     printf("little endian\n"); 
    } else if (echeck.i == 0x02010403) { 
     printf("pdp endian\n"); 
    } else { 
     printf("other endian\n"); 
    } 
    return 0; 
} 
+0

Удивительно, я не знал, что эти функции не были операциями на больших системах, это интересно. Благодаря! –

+0

Вы действительно имели в виду * php * -endian? Может быть, pdp-endian? –

+0

@R .. Да, это была опечатка. Исправлена. – dbush