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

我在little-endian [LE]机器[Linux,Intel处理器]上运行了以下程序。 我无法在下面的代码片段中解释3个输出。 由于机器是LE,a的值存储为0x78563412 。 打印时,它显示其实际值。 由于它是LE机器,我希望ntohl()成为无操作并显示0x78563412 ,它正在做。 但是,对于包含htonl()第二个print语句,我期望0x12345678 。 有人可以帮我理解他们为什么一样吗?

 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 

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

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

记住, htonl是你可以在主机上取一个整数,然后写:

 int i = htonl(a); 

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

并显示0x78563412

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

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

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

因为您传递的a by值,因此它们不会被这些函数中的任何一个更改。

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

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

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

但这并不是那么遥远,网络有序值通常在低级结构中保持这种方式,在发送之前或刚接收之后。

您的程序有什么问题,当您调用ntohl()您承诺使用ntohl()函数,您提供的int是按网络顺序存储在内存中的某些值。 这是合同。 如果不是这样,该function将无法执行您所期望的function,这就是您所看到的。

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