关于inet_ntoa函数的思考

204 篇文章 27 订阅
文章探讨了`inet_ntoa`函数在将整型IP地址转换为字符串时,由于使用静态变量导致的输出覆盖问题。通过示例代码展示了转换过程中因函数内部静态内存管理造成的意外结果,并分析了可能的解决方案,包括静态变量、全局变量和动态内存分配的优缺点。
摘要由CSDN通过智能技术生成

socket address的数据结构

​
/* Structure describing an Internet socket address.  */
struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;            /* Port number.  */
    struct in_addr sin_addr;        /* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
               __SOCKADDR_COMMON_SIZE -
               sizeof (in_port_t) -
               sizeof (struct in_addr)];
  };

​

 
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
 
 
void main()
{
    struct in_addr addr1, addr2;
    unsigned int uip1, uip2;
    uip1 = inet_addr("127.0.0.1");
    uip2 = inet_addr("172.16.16.123");
    printf("整数形式为:ip1=%u,ip2=%u\n",uip1,uip2);
 
    //相反过程
    memcpy(&addr1, &uip1, 4);
    memcpy(&addr2, &uip2, 4);
 
    printf("还原字符IP为:ip1=%s,ip2=%s\n",inet_ntoa(addr1),inet_ntoa(addr2));
 
    system("pause");
}

 
  1. 整数形式为:ip1=16777343,ip2=2064650412

  2. 还原字符IP为:ip1=127.0.0.1,ip2=127.0.0.1


可见,并不是我们预想的结果。这是为什么呢?我们知道,printf函数赋值是“从右到左”,也就是说出现了覆盖的问题。那我们来分析下函数inet_ntoa的内部实现机制。
函数inet_ntoa返回了一个字符指针。自动变量在堆栈中分配内存,当包含自动变量的函数或者代码退出时,它所占用的内存空间就会被回收,为了能够在函数或者代码退出时,仍然能够访问这些变量的内存(得到正确的结果),可以通过下面几种方法:
(1) 返回字符串常量。缺点是返回的字符串不能修改,显然inet_ntoa函数不会采用方法;
(2)定义一个全局变量。缺点是函数外的代码也可以修改,显然我们从inet_ntoa函数的输入输出看,也不会是这种方法;
(3)使用静态变量(在函数体内部),缺点是每次调用,就会覆盖上一次的内容,显然inet_ntoa函数就是采用的这种方式。先执行了inet_ntoa(addr2),修改静态变量为127.16.16.123,再执行inet_ntoa(addr1),修改静态变量为127.0.0.1,故而最终输出的时候都是127.0.0.1
(4)动态分配内存。(通过malloc等函数),我们设想如果inet_ntoa函数如果采用这种方式,那我们岂不没调用一次,还要释放一下内存?但是linux没有提供这种free的方法。
通过分析,inet_ntoa函数的输入参数是unsigned int类型的ip地址,返回的却是指向ip字符串的指针,很明显,ip字符串所占的内存是在函数内部分配的,而我们并不需要释放该内存, 所以,它分配的内存是静态的,也就是说下一次调用该函数时会覆盖这个数组的内容,所以就会出现上述的结果。

(1637条消息) 关于inet_ntoa函数的思考_形形色色的人的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值