inet_ntoa发生了什么?

时间:2017-12-25 17:15:06

标签: c sockets

让我感到困惑,有一个不同结果的例子。这对我来说有点不对。

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main(){
    struct sockaddr_in src;
    struct sockaddr_in dest;

    memset(&src, 0, sizeof(src));
    src.sin_addr.s_addr = 0xEBAE277D;

    memset(&dest, 0, sizeof(dest));
    dest.sin_addr.s_addr = 0x6700A8C0;

    printf("saddr:%s\n", inet_ntoa(src.sin_addr));
    printf("daddr:%s\n", inet_ntoa(dest.sin_addr));
    printf("src:%15s------->dest:%15s\n", inet_ntoa(src.sin_addr), inet_ntoa(dest.sin_addr));
}

结果:

saddr:125.39.174.235
daddr:192.168.0.103
src: 125.39.174.235------->dest: 125.39.174.235

1 个答案:

答案 0 :(得分:1)

inet_ntoa的文档说:

  

inet_ntoa()函数将以网络字节顺序给出的Internet主机地址转换为IPv4点分十进制表示法中的字符串。该字符串在静态分配的缓冲区中返回,后续调用将覆盖该缓冲区。

(那是来自Linux手册页;其他人有不同的措辞,但有关静态缓冲区的警告应该在某处)

所以你调用inet_ntoa一次,填充缓冲区,并返回指向它的指针。你再次调用它,缓冲区被覆盖,并再次返回指向它的指针。您将这两个指针都传递给了printf,并且它打印了两次缓冲区内容。

要正确执行此操作,您需要先将第一个inet_ntoa结果复制到您自己的本地缓冲区中,然后再重新调用它,或者只使用2 printf s。

或者您可以使用inet_ntop代替,这需要您自己提供输出缓冲区。 (调用者提供的输出缓冲区在较新的接口中更常见;静态输出缓冲区起初看起来很容易,但从长远来看会导致类似代码中的事故。)