为何printf同时打印多IP地址变量结果异常及修复方法
问题分析与解决
原因分析
inet_ntoa()函数的实现依赖静态缓冲区存储转换后的IP字符串,每次调用该函数都会覆盖这个缓冲区里的内容。当你在一个printf中连续传入两次inet_ntoa()调用时,多数C编译器会按从右到左的顺序求值函数参数:先执行inet_ntoa(ip_hdr->daddr)将结果写入静态缓冲区,接着执行inet_ntoa(ip_hdr->saddr)覆盖缓冲区内容。等printf真正读取参数时,两个占位符指向的都是同一个静态缓冲区的地址,最终显示的自然是最后一次转换的源地址。
修复方法
有三种常用解决方式:
- 分两次调用printf:每次调用仅传入一个
inet_ntoa()结果,避免缓冲区被覆盖。printf("源地址:%s\n", inet_ntoa(ip_hdr->saddr)); printf("目的地址:%s\n", inet_ntoa(ip_hdr->daddr)); - 提前将结果存入独立缓冲区:用两个字符数组分别存储两次转换后的IP字符串,再一起传入
printf。char src_ip[INET_ADDRSTRLEN]; char dst_ip[INET_ADDRSTRLEN]; strcpy(src_ip, inet_ntoa(ip_hdr->saddr)); strcpy(dst_ip, inet_ntoa(ip_hdr->daddr)); printf("源地址:%s,目的地址:%s\n", src_ip, dst_ip); - 使用线程安全的
inet_ntop()替代:inet_ntop()需要你自行提供缓冲区,不依赖静态存储,从根源上避免覆盖问题,同时支持IPv6,兼容性更好。char src_ip[INET_ADDRSTRLEN]; char dst_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(ip_hdr->saddr), src_ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(ip_hdr->daddr), dst_ip, INET_ADDRSTRLEN); printf("源地址:%s,目的地址:%s\n", src_ip, dst_ip);
内容的提问来源于stack exchange,提问作者Zulakis
相关产品推荐
相关产品推荐

