2

当我将 printf/printf_s 与两个字符串一起使用时,两个 %s 变量的输出相同。

IN_ADDR oldIP;
oldIP.S_un.S_addr = iptable[j]->ipAddress;
IN_ADDR newIP;
newIP.S_un.S_addr = adapterTbl->table[i].dwAddr;
printf_s("index %d old: %s new: %s", 
          adapterTbl->table[i].dwIndex, inet_ntoa(oldIP),
           inet_ntoa(newIP));

输出是:

index 11 old: 192.168.1.1 new: 192.168.1.1

现在,我通过在 print 语句之前中断来检查 oldip 和 newip 的值是否不同,并且我还尝试制作以下函数并在 print 语句中使用它(而不是 inet_ntoa):

char *convertIP (DWORD ip)  
{  
    IN_ADDR *addr = new IN_ADDR;
    memset(addr, 0, sizeof(IN_ADDR));
    addr->S_un.S_addr = (u_long) ip;
    return inet_ntoa(*addr);
} 

输出是:

192.168.1.1
192.168.1.2
index 11 old: 192.168.1.1 new: 192.168.1.1

为什么我会看到这种行为,我该如何解决?
谢谢 :)

4

2 回答 2

6

inet_ntoa返回:

一个静态分配的缓冲区,后续调用会覆盖

(这来自 Linux 联机帮助页。)

您不能在函数中使用它两次,只有第二次调用的输出是可见的(并且您不知道两个调用中的哪一个是第二次调用 - 未指定函数参数的评估顺序)。

做两个单独printf的 s,或将输出复制inet_ntoa到本地缓冲区并输出那些。

POSIX

inet_ntoa ()的返回值可能指向静态数据,这些静态数据可能会被后续对inet_ntoa () 的调用覆盖。

所以这种行为可能并不局限于Linux,你不能依赖它覆盖静态缓冲区。

于 2012-04-03T20:07:34.020 回答
1

由于 Mat 描述的原因,您必须inet_ntoa在执行下一次调用之前使用一次调用的结果。

这是一种简单的方法:

IN_ADDR oldIP;
oldIP.S_un.S_addr = iptable[j]->ipAddress;
IN_ADDR newIP;
newIP.S_un.S_addr = adapterTbl->table[i].dwAddr;
std::string s_old(inet_ntoa(oldIP));
std::string s_new(inet_ntoa(newIP));
printf_s("index %d old: %s new: %s", 
      adapterTbl->table[i].dwIndex, s_old.c_str(),
       s_new.c_str());

请注意,string构造函数会复制传入的 C 字符串。因此,当inet_ntoa再次调用时,它可以自由地覆盖其先前存储的值。

于 2012-04-03T20:20:27.133 回答