为什么在printf中调用两次的inet_ntoa给出错误的输出?

anu*_*amb 3 c networking

我写了一个代码,但是我不确定为什么最后一个printf给出了意外的结果。我的命令行参数分别是12和15。代码如下:

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

int main(int argc, char *argv[])
{
  struct in_addr adr, adr2;
  int num, num2;

  num = atoi(argv[1]);
  num2 = atoi(argv[2]);

  adr.s_addr = htonl(num);
  adr2.s_addr = htonl(num2);

  printf("%x %x\n", num, adr.s_addr); # c c000000
  printf("%x %x\n", num2, adr2.s_addr); # f f000000

  printf("%s\n", inet_ntoa(adr)); # 0.0.0.12
  printf("%s\n", inet_ntoa(adr2)); # 0.0.0.15
  printf("%s %s\n", inet_ntoa(adr), inet_ntoa(adr2)); # 0.0.0.12 0.0.0.12
  return(0);
}
Run Code Online (Sandbox Code Playgroud)

我期望最终输出为“ 0.0.0.12 0.0.0.15”,但事实并非如此。谁能帮忙吗?

dbu*_*ush 5

inet_ntoa函数返回一个指向静态缓冲区的指针。在这种情况下,该函数作为另一个函数的参数被两次调用。函数参数的求值顺序不确定,因此静态缓冲区的内容将是最后运行的那个。并且由于它总是返回相同的缓冲区,因此相同的东西将被打印两次。

因此,如果没有中间的顺序点(即单独的语句,短路运算符,例如&&||,逗号运算符或三元运算符),您不能多次调用这样的函数。

在此特定代码的情况下,两个单独的调用分别调用printf一次inet_ntoa(就像您在前两行中所做的那样)是正确的方法。

另外,如果您打算将函数的结果保存在某个地方,则不能只保存指针,因为它指向的数据每次都会被更改inet_ntoa。您需要使用strcpy或复制它strdup