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

问题描述 投票:3回答:1

我写了一个代码,但我不确定为什么最后一个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);
}

我预计最终输出为“0.0.0.12 0.0.0.15”,但事实并非如此。有人可以帮忙吗?

c networking
1个回答
5
投票

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

所以你不能在没有插入序列点的情况下更多地调用这样的函数,即单独的语句,短路运算符,如&&||,逗号运算符或三元运算符。

在这个特定代码的情况下,对printf的两次单独调用每次调用inet_ntoa(正如你在前两行中所做的那样)是正确的方法。

此外,如果您计划在某个地方保存此函数的结果,则不能只保存指针,因为每次调用inet_ntoa时它指向的数据都会更改。您需要使用strcpystrdup复制它。

© www.soinside.com 2019 - 2024. All rights reserved.