C语言变长数组data[0]【总结】

1、前言

  

  今天在看代码中遇到一个结构中包含char data[0],第一次见到时感觉很奇怪,数组的长度怎么可以为零呢?于是上网搜索一下这样的用法的目的,发现在linux内核中,结构体中经常用到data[0]。这样设计的目的是让数组长度是可变的,根据需要进行分配。方便操作,节省空间。

2、data[0]结构

经常遇到的结构形状如下:

struct buffer
{int data_len;   //长度char data[0];  //起始地址
};

在这个结构中,data是一个数组名;但该数组没有元素;该数组的真实地址紧随结构体buffer之后,而这个地址就是结构体后面数据的地址(如果给这个结构体分配的内容大于这个结构体实际大小,后面多余的部分就是这个data的内容);这种声明方法可以巧妙的实现C语言里的数组扩展。

  

  写个程序对比char data[0],char *data, char data[],如下所示:

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stdint.h>
 5
 6 typedef struct
 7 {
 8     int data_len;
 9     char data[0];
10 }buff_st_1;
11
12 typedef struct
13 {
14     int data_len;
15     char *data;
16 }buff_st_2;
17
18 typedef struct
19 {
20     int data_len;
21     char data[];
22 }buff_st_3;
23
24 int main()
25 {
26     printf("sizeof(buff_st_1)=%u\n", sizeof(buff_st_1));
27     printf("sizeof(buff_st_2)=%u\n", sizeof(buff_st_2));
28     printf("sizeof(buff_st_3)=%u\n", sizeof(buff_st_3));
29
30     buff_st_1 buff1;
31     buff_st_2 buff2;
32     buff_st_3 buff3;
33
34     printf("buff1 address:%p,buff1.data_len address:%p,buff1.data address:%p\n",
35         &buff1, &(buff1.data_len), buff1.data);
36
37     printf("buff2 address:%p,buff2.data_len address:%p,buff2.data address:%p\n",
38         &buff2, &(buff2.data_len), buff2.data);
39
40     printf("buff3 address:%p,buff3.data_len address:%p,buff3.data address:%p\n",
41         &buff3, &(buff3.data_len), buff3.data);
42
43     return 0;
44 }

从结果可以看出data[0]和data[]不占用空间,且地址紧跟在结构后面,而char *data作为指针,占用4个字节,地址不在结构之后。

3、实际当中的用法

在实际程序中,数据的长度很多是未知的,这样通过变长的数组可以方便的节省空间。对指针操作,方便数据类型的转换。测试程序如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stdint.h>
 5
 6 typedef struct
 7 {
 8     int data_len;
 9     char data[0];
10 }buff_st_1;
11
12 typedef struct
13 {
14     int data_len;
15     char *data;
16 }buff_st_2;
17
18 typedef struct
19 {
20     int data_len;
21     char data[];
22 }buff_st_3;
23
24 typedef struct
25 {
26     uint32_t id;
27     uint32_t age;
28 }student_st;
29
30
31 void print_stu(const student_st *stu)
32 {
33     printf("id:%u,age:%u\n", stu->id, stu->age);
34 }
35
36 int main()
37 {
38     student_st *stu = (student_st *)malloc(sizeof(student_st));
39     stu->id = 100;
40     stu->age = 23;
41
42     student_st *tmp = NULL;
43
44     buff_st_1 *buff1 = (buff_st_1 *)malloc(sizeof(buff_st_1) + sizeof(student_st));
45     buff1->data_len = sizeof(student_st);
46     memcpy(buff1->data, stu, buff1->data_len);
47     printf("buff1 address:%p,buff1->data_len address:%p,buff1->data address:%p\n",
48         buff1, &(buff1->data_len), buff1->data);
49
50     tmp = (student_st*)buff1->data;
51     print_stu(tmp);
52
53     buff_st_2 *buff2 = (buff_st_2 *)malloc(sizeof(buff_st_2));
54     buff2->data_len = sizeof(student_st);
55     buff2->data = (char *)malloc(buff2->data_len);
56     memcpy(buff2->data, stu, buff2->data_len);
57     printf("buff2 address:%p,buff2->data_len address:%p,buff2->data address:%p\n",
58         buff2, &(buff2->data_len), buff2->data);
59
60     tmp = (student_st *)buff2->data;
61     print_stu(tmp);
62
63     buff_st_3 *buff3 = (buff_st_3 *)malloc(sizeof(buff_st_3) + sizeof(student_st));
64     buff3->data_len = sizeof(student_st);
65     memcpy(buff3->data, stu, buff3->data_len);
66     printf("buff3 address:%p,buff3->data_len address:%p,buff3->data address:%p\n",
67         buff3, &(buff3->data_len), buff3->data);
68
69     tmp = (student_st*)buff1->data;
70     print_stu(tmp);
71
72     free(buff1);
73
74     free(buff2->data);
75     free(buff2);
76
77     free(buff3);
78     free(stu);
79     return 0;
80 }

程序执行结果如下:
  采用char *data,需要进行二次分配,操作比较麻烦,很容易造成内存泄漏。而直接采用变长的数组,只需要分配一次,然后进行取值即可以。

C语言变长数组data[0]【总结】相关推荐

  1. C语言变长数组 struct中char data[0]的用法

    摘要:在实际的编程中,我们经常需要使用变长数组,但是C语言并不支持变长的数组.此时,我们可以使用结构体的方法实现C语言变长数组. struct MyData  {  int nLen;  char d ...

  2. C语言变长数组(柔性数组)

    变长数组(柔性数组) C99支持变长数组,定义时可以不指定数组长度,分配时再根据实际长度进行分配. 变长数组一般只能放在结构体的最后一个成员, 在变长数组之前至少得有一个结构体成员 且一个结构体只能有 ...

  3. 第六章 C语言数组_C语言变长数组:使用变量指明数组的长度

    在<C语言的三套标准:C89.C99和C11>一节中我们讲到,目前经常使用的C语言有三个版本,分别是 C89.C99 和 C11.C89(也称 ANSI C)是较早的版本,也是最经典的版本 ...

  4. c语言变长数组参数,使用gdb跟踪C语言中变长数组的实现

    项目的代码中出现的一个问题,问题的表现是,在一个函数中使用到了变长数组,而对超过这个数组 范围的一个赋值,导致了数组首地址为空. 我把这个问题抽出来形成了一个示例函数,在i386下也出现类似的问题,代 ...

  5. c99变长数组_C语言变长数组使用详解

    看如下代码: #include typedef struct { int len; int array[]; }SoftArray; int main() { int len = 10; printf ...

  6. c语言变长数组_2018级C语言大作业 - 祖玛

    C语言 - 祖玛https://www.zhihu.com/video/1226223520021295104 分享18级同学大一上学期用C语言实现的祖玛.分步骤代码.图片音乐素材.可执行程序可从百度 ...

  7. C语言,变长数组的用法

    ​ 在我的<C语言,结构体成员的地址>文章中,定义了一个demo_node结构体,其中用到变长数组char addr[0].本文以此为例,对C语言变长数组的基本用法展开介绍. #pragm ...

  8. C语言高级教程-C语言数组(六):变长数组

    C语言高级教程-C语言数组(六):变长数组 一.本文的编译环境 二.一维数组在执行期间确定长度 三.二维数组在执行期间确定长度 四.一维变长数组实例 五.完整程序 5.1 Main.h 文件程序 5. ...

  9. c++什么时候数组溢出_C语言,营养丰富的C语言五,变长数组不是动态数组

    大家好,感谢朋友的支持阅读和关注,虽然我提出的这些小知识点看得人很少,但是每涨一个阅读和关注,都能让我开心很久,所以再次感谢一起学习的朋友们. 查余补漏: 在前几次的讲解中,有朋友提出C语言的内存分配 ...

最新文章

  1. 线程通信问题--生产者和消费者问题
  2. 原来流行也可以变成怀旧!
  3. 笔记-信息系统开发基础-CMMI组织能力成熟度模型-连续式和阶梯式的分组
  4. redis的安装和测试
  5. 服务器消除报警信息,巧妙设置让故障服务器自动报警的小技巧
  6. python基础系列教程——python基础语法全解
  7. StorAge存储库
  8. Nginx面试题整理
  9. 读react.js小书 抽象公共组件类
  10. java/php/net/python大学生就业管理系统设计
  11. Nacos 服务注册中心
  12. 标准盒模型和IE盒模型
  13. html验证座机号码_手机号码 座机号码验证
  14. 袋鼠云数据中台专栏2.0 | 数据中台之数据源
  15. Pytorch实现人脸多属性识别
  16. 5分钟弄懂语音识别技术原理
  17. 【视觉的盛宴】-圣托里尼、爱琴海
  18. 制作一个简单HTML电影网页设计(HTML+CSS)
  19. 融合柯西变异和反向学习的改进麻雀算法
  20. div固定在浏览器顶部

热门文章

  1. 算法竞赛入门经典 第一章 上机练习(C++代码)
  2. QuerySyntax(查询语法)
  3. iOS开发-平台使用TestFlight进行Beta测试
  4. 一个优雅的占位图解决方案。适用于 UITableView 和 UICollectionView。
  5. .Net Core2.*学习手册
  6. Flash基本工具练习
  7. Ctrl+F5不能使用的问题
  8. 怎样和客户一起搞定需求
  9. [导入]关于阶乘的两个常见算法及一个相关面试题
  10. 为什么要用TypeScript - 肉猪 - 博客园