htonl()和ntohl()对整数的输出相同

时间:2012-07-10 23:11:25

标签: c endianness

我在little-endian [LE]机器[Linux,Intel处理器]上运行了以下程序。我无法在下面的代码片段中解释3个输出。由于机器是LE,因此a的值存储为0x78563412。打印时,它显示其实际值。由于它是LE机器,我希望ntohl()是一个无操作并显示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

4 个答案:

答案 0 :(得分:23)

  

由于它是LE机器,我希望ntohl()成为无操作

这是错误的。网络字节顺序为 big-endian ,主机字节顺序为little-endian。因此,ntohlhtonl都会返回其输入的字节交换版本。

请记住,htonl的要点是您可以在主机上取整数,然后写:

int i = htonl(a);

结果是i的内存在使用网络字节顺序解释时,具有与a相同的值。因此,如果将i的对象表示写入套接字,而另一端的阅读器需要网络字节顺序的4字节整数,则它将读取a的值。

  

并显示0x78563412

这是你打算写的吗?如果ntohl是无操作(或者更确切地说是身份函数),那么您的第三行必然会打印与第一行相同的内容,因为您将拥有ntohl(a) == a。这是在程序打印的big-endian实现中发生的事情:

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

答案 1 :(得分:11)

htonlntohl功能完全相同。他们应该满足htonl(ntohl(x)) == x。它们的命名方式不同仅适用于文档(您明确指出要从主机到网络或其他方式进行转换,即使它们是相同的)。因此,在小端机器上,它们都执行字节交换,而在大端机器上,它们都是无操作的。

答案 2 :(得分:5)

因为您按值传递a因此不会被其中任何一个函数更改。

您正在打印htonl()ntohl() 返回的内容。

编辑添加:我错过了您认为其中一个无操作的地方。不是。两者都将在LE机器上做同样的事情;反转字节排序。 ntohl()期待您传递一个排序为int

的网络字节

答案 3 :(得分:0)

在您的程序中,当您编写int a; 知道a包含主机有序整数时,程序并不知道。您可以轻松地提供已经包含网络顺序值的int。当然,如果对非主机顺序的值使用任何算术运算符,如果网络顺序与主机顺序不同,则从网络角度来看结果将是错误的。

但目前还不是这样,网络有序值通常在低级结构中保持这种状态,在发送之前或刚接收之后。

你的程序有什么问题,当你致电ntohl()时,你承诺ntohl()函数,你提供的int是一些以网络顺序存储在内存中的值。这是合同。如果不成功,该功能将无法满足您的期望,而这正是您所期待的。

正如大多数系统(大或小但不是愚蠢的端)所解释的那样,这两个函数通常是相同的,无论是字节反转还是无操作。