当我使用带有两个字符串的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
为什么我会看到这种行为,我该如何解决? 谢谢:))
答案 0 :(得分:6)
inet_ntoa
返回:
静态分配的缓冲区,后续调用覆盖
(这是来自Linux联机帮助页。)
你不能在函数中使用它两次,只有第二次调用的输出才会可见(并且你不知道这两个调用中的哪一个是第二个 - 函数参数的评估顺序是未指定)。
执行两个单独的printf
,或将inet_ntoa
的输出复制到本地缓冲区并输出。
来自POSIX:
inet_ntoa ()的返回值可能指向可能被后续调用 inet_ntoa ()覆盖的静态数据。
所以这种行为可能不仅限于Linux,你也不能依赖它而不是覆盖静态缓冲区。
答案 1 :(得分: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
时,可以自由覆盖其先前存储的值。