Тот же вывод для htonl() и ntohl() для целого числа

Я запустил следующую программу на машине little-endian [LE] [Linux, процессор Intel]. Я не могу объяснить три вывода в ниже фрагменте кода. Так как машина LE, значение a сохраняется как 0x78563412. При печати отображается фактическое значение. Начиная с его машины LE, я ожидаю, что ntohl() будет no-op и отобразит 0x78563412, что он делает. Тем не менее, я ожидаю, что 0x12345678 для второго оператора печати, содержащего htonl(). Может кто-то, пожалуйста, помогите мне понять, почему они такие же?

int main() 
{
    int a = 0x12345678; 

    printf("Original - 0x%x\n", (a)); 
    printf("Network - 0x%x\n", htonl(a)); 
    printf("Host - 0x%x\n", ntohl(a)); 

    return 0;
}

Вывод:

Original - 0x12345678
Network - 0x78563412
Host - 0x78563412

Ответ 1

Начиная с его машины LE, я ожидаю, что ntohl() будет no-op

Это ошибка. Сетевой порядок байтов является бай-ином, порядок байтов хоста носит малозначительный характер. Поэтому как ntohl и htonl возвращают байтовую версию их ввода.

Помните, что точка htonl состоит в том, что вы можете взять целое число на хосте, а затем написать:

int i = htonl(a);

и результатом является то, что память i, когда интерпретируется с использованием сетевого порядка следования байтов, имеет то же значение, что делает. a Следовательно, если вы пишете представление объекта i в сокет, а читатель с другого конца ожидает целое число из 4 байтов в сетевом байтовом порядке, он будет читать значение a.

и дисплей 0x78563412

Это то, что вы намеревались написать? Если ntohl был не-op (вернее, функцией идентификации), то ваша третья строка обязательно напечатала бы то же самое, что и ваша первая строка, потому что у вас было бы ntohl(a) == a. Это то, что происходит в реализациях большого конца, где печатается ваша программа:

Original - 0x12345678
Network - 0x12345678
Host - 0x12345678

Ответ 2

htonl и ntohl - это точно такие же функции. Предполагается, что они удовлетворяют htonl(ntohl(x)) == x. Они называются по-разному только для документации (вы делаете это явным, что вы конвертируете из хоста в сеть или наоборот, даже если это то же самое). Таким образом, на машине с маленькими терминами они выполняют как байтовую замену, так и на машине большого конца, они оба не работают.

Ответ 3

Потому что вы передаете по значению и, следовательно, не изменяется ни одним из этих функций. a

Вы печатаете то, что htonl() и ntohl().

Изменить, чтобы добавить: я пропустил, где вы считали, что это будет не-op. Не это. Оба будут делать то же самое на машине LE; отмените порядок байтов. ntohl() ожидает, что вы ntohl() ему сетевой байт, заказанный int

Ответ 4

В вашей программе, когда вы пишете int a; вы знаете, что a содержит целое число, назначенное хостом, программа этого не знает. Вы могли бы легко предоставить int, уже содержащий значение в сетевом порядке. Конечно, если вы используете какой-либо арифметический оператор для значения, которое не находится в порядке хоста, результат будет неверным с точки зрения сети, если порядок сети не совпадает с порядком хоста.

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

Что не так с вашей программой, так это то, что когда вы вызываете ntohl() вы ntohl() функцию ntohl() которую вы предоставляете int, - это некоторое значение, хранящееся в памяти в сетевом порядке. Это договор. Если это не так, функция не будет выполнять то, что вы ожидаете, и это то, что вы делаете.

Как и другие объяснения в большинстве систем (больших или маленьких, но не глупых-endians), две функции обычно идентичны, либо байтовые обратные, либо нет-op.