结构体 — C 语言中不定长结构体的使用
1、结构体的定长表示
C语言中结构体的使用基本上都是定长的,就如以下这种:
typedef struct
{int a;int b;char c[100];double d;
}STRU;
2、结构体的不定长表示
2.1、指针形式
但在很多的场景下,结构体的定义成不定长反而更容易解决问题,最典型的就是需要通过Socket发送一个结构体数据,但是结构体中包含了一个不定长的信息。可以采用以下方式来定义结构体:
typedef struct
{int a;char *b;char *c;
}STRU;
对于该种类型的结构体可以采用以下两种方式来申请并分配内存:
1)、直接分配
char b[] = "ahsdggc adgfas";char c[] = "asjdhvbaegegfgasdjv";int len = sizeof(STRU);int len_b = strlen(b)+1; //+1是因为字符串有一个字节存放'\0'int len_c = strlen(c)+1;STRU *stru = (STRU *)malloc(len + len_b + len_c);memset(stru, 0, len);printf("Before - STRU 的地址为:%x \n", stru);printf("Before - STRU_B 的地址为:%x \n", stru->b);printf("Before - STRU_C 的地址为:%x \n", stru->c);stru->b = (char *)stru + len; //重新分配 stru->b 的地址stru->c = stru->b + len_b; //重新分配 stru->c 的地址printf("After - STRU 的地址为:%x \n", stru);printf("After - STRU_B 的地址为:%x \n", stru->b);printf("After - STRU_C 的地址为:%x \n", stru->c);strcpy(stru->b, b); //将 b 的内容复制到 stru->bstrcpy(stru->c, c); //将 c 的内容复制到 stru->ccout << ">>> b: " << stru->b << endl;cout << ">>> c: " << stru->c << endl;
运行的结果如下所示:
2)、 间接分配
还有另外一种分配的方式:
char b[] = "ahsdggc adgfas";char c[] = "asjdhvbaegegfgasdjv";int len = sizeof(STRU);int len_b = strlen(b)+1; //+1是因为字符串有一个字节存放'\0'int len_c = strlen(c)+1;STRU *stru = (STRU *)malloc(len);memset(stru, 0, len);char *cb = (char *)calloc(0, len_b); // 申请 len_b 长的内存并初始化为0memcpy(cb, b, len_b); // 将 b 的内容复制到 cb 中char *cc = (char *)calloc(0, len_c); // 申请 len_c 长的内存并初始化为0memcpy(cc, c, len_c); // 将 c 的内容复制到 cc 中printf("Before - STRU 的地址为:%x \n", stru);printf("Before - STRU_B 的地址为:%x \n", stru->b);printf("Before - STRU_C 的地址为:%x \n", stru->c);printf("Before - cb 的地址为:%x \n", cb);printf("Before - cc 的地址为:%x \n", cc);stru->b = cb;stru->c = cc;printf("After - STRU_B 的地址为:%x \n", stru->b);printf("After - STRU_C 的地址为:%x \n", stru->c);printf("After - cb 的地址为:%x \n", cb);printf("After - cc 的地址为:%x \n", cc);cout << ">>> b: " << stru->b << endl;cout << ">>> c: " << stru->c << endl;
下图为验证的结果:
以上两种方式,一个是在申请结构体的内存时也分配字符串长度的内存;还有一种是先分配结构体的内存,然后再申请结构体长度的内存,然后通过地址赋值的方式使结构体中的元素指向那些内存;
2.2、空数组方式
但是还有一种形式的结构体:
typedef struct
{int a;int b;char c[0];
}STRU;
在上面的定义中,char c[0]定义了一个长度为0的字符串数组,此时,在结构体中实际上只包含了a和b的地址空间,即sizeof(STRU)== 8,
此时c被当成一个指针,指向了结构体后面的内存地址的起始地址,c = &stru + sizeof(STRU),如下所示:
struct test3{int a;int b;char c[0]; //不占用结构体的内存地址,此时c指向的就是结构体后面的内存空间的起始地址
};test3 t3;
test3* pt3 = &t3;
printf("t3 address: %x\n", pt3);
printf("t3.c address: %x\n", t3.c);
cout << "sizeof(test3) = " << sizeof(test3) << endl; //8
最终输出结果为:
这样就可以直接将结构体后面的数据当成字符串数组c的内容 ,这种使用方式被称为柔性数组,关于柔性数组的更多内容可以参考:https://www.cnblogs.com/pluviophile/p/7571410.html
结构体 — C 语言中不定长结构体的使用相关推荐
- c语言如何宏定义枚举型结构体,C语言学习笔记--枚举结构体
枚举 枚举是一种用户定义的数据类型,它用关键字enum以如下语法格式来声明: enum 枚举类型名字 {名字0,名字1,...,名字n}: 枚举类型名字通常并不真的使用,要用的是大括号里面的名字,因为 ...
- c语言自定义的结构体,c语言定义多个结构体
本文收集整理关于c语言定义多个结构体的相关议题,使用内容导航快速到达. 内容导航: Q1:C语言中定义一个结构体如何在不同的.C文件中使用. #include 然后就用啊 正式一点的,可以声明 ext ...
- C语言中的分支结构和循环结构有哪些,【单选题】下面哪种不是C语言中的基本结构______。
A. 顺序结构 B. 分支结构 C. 跳转结构 D. 循环结构...
[单选题]下面哪种不是C语言中的基本结构______. A. 顺序结构 B. 分支结构 C. 跳转结构 D. 循环结构 更多相关问题 [单选,A2型题,A1/A2型题] 金瓷基底冠进行氧化处理时,理想 ...
- C语言 函数不定长参数 ##__VA_ARGS__经典案例 - C语言零基础入门教程
目录 一.##__VA_ARGS__简介 二.##__VA_ARGS__经典案例 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.## ...
- C语言 函数不定长参数 - C语言零基础入门教程
目录 一.前言 二.函数不定长参数简介 1.va_start 2.va_arg 3.va_end 三.自定义不定长参数的函数 1.va_start/va_arg/va_end 案例一 2.va_sta ...
- storm目录结构及在zk中的目录结构
storm目录结构及在zk中的目录结构 @(STORM)[storm] storm目录结构及在zk中的目录结构 一storm在磁盘中的内容 一nimbus中的目录结构 1inbox目录 2stormd ...
- java 不定参数方法_java中不定长参数的使用方法
java中不定长参数的使用方法 不定长参数方法的语法如下:返回值 方法名(参数类型...参数名称) 在参数列表中使用"..."形式定义不定长参数,其实这个不定长参数a就是一个数组, ...
- java 不定参数_java中不定长参数的实例用法
java中不定长参数的使用方法 不定长参数方法的语法如下: 返回值 方法名(参数类型...参数名称) 在参数列表中使用"..."形式定义不定长参数,其实这个不定长参数a就是一个数组 ...
- c语言不同类型指针间的强转,C语言中不同的结构体类型的指针间的强制转换详解...
C语言中不同类型的结构体的指针间可以强制转换,很自由,也很危险.只要理解了其内部机制,你会发现C是非常灵活的. 一. 结构体声明如何内存的分布, 结构体指针声明结构体的首地址, 结构体成员声明该成员在 ...
最新文章
- [软件工程基础]团队作业Week3
- Hyperledger Besu企业以太坊快速教程
- 在C#中利用SharpZipLib进行文件的压缩和解压缩
- YUV2RGB源码详解(参考Opencv4.1)
- std::recursive_mutex嵌套锁/递归锁
- 中国国民休闲状况调查(2020)
- 微软发布了Visual Stduio 2010 RTM版本的虚拟机vhd文件,包含样例和动手实验(免费)...
- MFC中使用CTabCtrl或CPropertySheet实现标签页
- Ubuntu21.04安装网易有道词典
- ssh整合之四单独搭建struts的运行环境
- Linux中级之netfilter/iptables应用及补充
- 允许外部访问Windows本机的指定端口
- win10 html字体设置,IT之家学院:如何解决Win10屏幕字体缩放模糊问题
- hashMap底层原理
- 吴恩达—机器学习的六个核心算法
- 哪款投影仪做家庭影院效果好?家用投影仪哪个好
- win7系统ftp服务器构建,win7系统构建ftp服务器
- Android 手札小记
- uniapp 基础框架模板
- 【单细胞分析】P2.5、聚类,筛选marker基因,可视化
热门文章
- <12>springboot集成thymeleaf模板引擎
- 关于VS2017许可证过期问题
- 漫步者蓝牙自动断开_比苹果AirPods体验更好的蓝牙耳机,漫步者lollipods体验小感...
- linux操作系统具有哪些特性,Linux系统拥有哪些特性?这些你必须知道!
- twitter三方登录的实现
- 积分球辐射光源照度均匀性
- 可能改变世界的13个“终结”(上)
- 赛氪2020上半年 A.转换AV号(avtobv)[神奇的输入][神奇的getchar()][进制转换]
- OB0201 obsidian dataview插件使用
- 视频监控系统 摄像头与网络存储服务器兼容,网络视频监控系统技术要点