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 :)
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.
For the reasons that Mat described, you must use the result of one call to inet_ntoa before performing the next call. 
Here is one easy way to do that:
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());
Note that the string constructor makes a copy of the passed-in C string. Thus, when inet_ntoa is invoked again, it is free to overwrite its previously-stored value.