Search code examples
c++printfinet

Bad behavior with printf and multiple strings


When I use printf/printf_s with two strings, I get the same output for both %s vars.

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));

Output is:

index 11 old: 192.168.1.1 new: 192.168.1.1

Now, I have checked that the values of oldip and newip are different by breaking before the print statement, and I have also tried to make the following function and use it in the print statement (instead of 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);
} 

The output with this was:

192.168.1.1
192.168.1.2
index 11 old: 192.168.1.1 new: 192.168.1.1

Why am I seeing this behavior, and how can I fix it?
Thanks :)


Solution

  • inet_ntoa retuns:

    a statically allocated buffer, which subsequent calls overwrite

    (This is from the Linux manpage.)

    You can't use it twice in a function, only the output of the second call will be visible (and you don't know which one of the two calls is the second - order of evaluation of arguments to a function is unspecified).

    Do two separate printfs, or copy the output of inet_ntoa to local buffers and output those.

    From POSIX:

    The return value of inet_ntoa() may point to static data that may be overwritten by subsequent calls to inet_ntoa().

    So this behavior is probably not limited to Linux, and you can't rely on it not overwriting a static buffer.