首页 > 其他分享 >C语言网络接口函数inet_ntoa用法小坑与分析

C语言网络接口函数inet_ntoa用法小坑与分析

时间:2022-10-22 15:32:46浏览次数:45  
标签:C语言 char str ntoa include ptr inet



tags: C Network Debug

问题

今天看了一下网络编程, 发现其中有一个接口函数很有意思, 就是从二进制转换到点分十进制表示的IP地址 的函数​​inet_ntoa()​​, 直接使用倒是没什么异样, 但是下面一个例子却出现了一个很有趣的现象:

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

int main(int argc, char *argv[]) {
struct sockaddr_in addr1, addr2;
char *str_ptr;
char str_arr[20];

addr1.sin_addr.s_addr = htonl(0x1020304);
addr2.sin_addr.s_addr = htonl(0x1010101);

str_ptr = inet_ntoa(addr1.sin_addr);
strcpy(str_arr, str_ptr);
printf("Dotted-Decimal notation1: %s \n", str_ptr);

inet_ntoa(addr2.sin_addr);
printf("Dotted-Decimal notation2: %s \n", str_ptr);
printf("Dotted-Decimal notation3: %s \n", str_arr);

/*
Dotted-Decimal notation1: 1.2.3.4
Dotted-Decimal notation2: 1.1.1.1
Dotted-Decimal notation3: 1.2.3.4
*/

return 0;
}

这个例子是引用​​TCP/IP网络编程​​​这本书上的, 可以看出第二次调用​​inet_ntoa()​​​时候并没有将返回值赋值给变量​​str_ptr​​, 但是输出这个变量的时候还是发生了改变, 这是为什么呢?

书中给出的解释是:

该两数将通过参数传入的整数型地址转换为字符串格式并返回。但调用时需小心,返回值
类型为​​​char​​​指针。返回宇符串地址意味着字符串已保存到内存空间,但该函数未向程序员要求分
配内存,而是在内部申请了内存并保存了宇符串。也就是说,调用完该函数后,应立即将字符串
信息复制到其他内存空间。因为,若再次调用​​​inet_ntoa​​​函数.则有可能覆盖之前保存的字符串信
息。总之,再次调用​​​inet_ntoa​​​函数前返回的宇符串地址值是有效的。若需要长期保存,则应将字
符串复制到其他内存空间。

也就是说, 其内部会首先分配一段空间, 用来保存转换后的字符串, 所以第二次调用的时候虽然没赋值给​​str_ptr​​, 但是该变量仍能获取到这个值(通过指针).

通过查看​​man inet_ntoa​​发现:

The string returned by inet_ntoa() resides in a static memory area.

inet_ntoa()返回的字符串驻留在静态内存区域。

这就是说其内部分配的是一份静态变量, 所以才导致了上述问题出现.

例子

下面来看一个我自己写的例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* f1(int a) {
static char pp[20];
char *c1 = "123", *c2 = "456";
if (a) {
strcpy(pp, c1);
} else {
strcpy(pp, c2);
}
return pp;
}
int main(int argc, char* argv[]) {
char* p;
p = f1(1);
printf("%s", p);//123
f1(0);
printf("%s", p);//456
return 0;
}

乍一看大家可能以为结果会是​​123123​​​, 因为第二次调用并没有改变​​p​​​的值, 但是由于在函数​​f1()​​​的​​char pp[20]​​​变量前面加上了​​static​​​, 使​​pp[20]​​​成为静态变量, 这就保存在全局变量区了, 在​​f1​​​函数结束之后变量也不会销毁, 所以才能由指针​​p​​去获取一个新得到的值, 从而可以不赋值就能改值了.


标签:C语言,char,str,ntoa,include,ptr,inet
From: https://blog.51cto.com/u_15366127/5785895

相关文章

  • C语言实现vector结构
    C语言实现vector结构 1.使用说明本例vector结构以单链表方式实现,结合了stack与queue结构:pop_front+push_front使用方式为stack;pop_front+push_back使用方式是queue。......
  • 初学c语言的感悟
          我现在已经大二了,大一下学期没有跟着老师学习,所以趁现在及时补救,在网上自学C语言。    我觉得学习C语言和学习英语差不多,有许多的规则,基本的语句......
  • 【C语言游戏】三子棋完整代码和正确结果截图
    ......
  • C语言逻辑推理题谁是凶手
    C语言逻辑推理题谁是凶手假定一个岛上住着三类人:骑士、无赖和普通人(也称为间谍)。骑士总是说真话,无赖总是说假话,普通人有时说谎话有时说真话。侦探为了调查一宗罪案,而询问......
  • C语言输入输出测试
    一、输入测试(1)输入数值测试三个%d之间的间隔分别为(无)(逗号)(空格)三种情况,应该如何正常输入,要求得到正确输出间隔分别为(空格时候),输入的时候以回车间隔是否可以?#include<......
  • C语言中的getchar、putchar函数
    getchar可以接受键盘上打印的字符,puchar可以进行输出字符比如:#include<stdio.h>intmain(){intch=getchar();putchar(ch);printf("%c\n",ch);return0;}运......
  • C语言实现模拟用户登录
    一.问题要求模拟用户登录情况,用户输入密码,如果密码正确就提示登陆成功,错误就显示登录失败,且只能有三次机会,输入错误三次就退出程序二.解决思路我们可以先确定一个密码,然后用......
  • c语言—调试篇—笔记
    调试#include<stdio.h>intmain(){char*p="hellobit.";printf("%s\n",p);return0;}#include<stdio.h>intmain(){inti=0;intarr[10]={0};for(i=0;i<=12;i++......
  • C语言-结构体
    (5条消息)C语言中的结构体(struct)___Sunshine_的博客-CSDN博客_结构体......
  • 【C语言】数组
    ......