GNU C 中的零长数组
文章目录
- 什么是零长数组(Arrays of Length Zero)
- 零长数组的使用
- 零长数组和指针的区别
- 定义什么类型的零长数组
什么是零长数组(Arrays of Length Zero)
如果我们在程序中定义一个零长度数组,你会发现除了 GCC 编译器,在其它编译环境下可能就编译通不过或者有警告信息。
咱们看一个很简单的例子:
int buffer[0];
int main(void)
{printf("%d\n", sizeof(buffer));return 0;
}
你会发现,输出结果是 0
也就是说,长度为 0 的数组是不占用内存空间的。
零长数组的使用
但是,零长度数组一般不单独使用,它常常作为结构体的最后一个成员,构成一个变长结构体。我们看一个例子
#include <string.h>
#include <stdlib.h>
#include <stdio.h>struct line {short len;char contents[0];
};int main(void)
{const char *txt = "hello";int my_len = strlen(txt) + 1;struct line *my_line = (struct line *) malloc (sizeof (struct line) + my_len);my_line->len = my_len; memcpy(my_line->contents, txt, my_len);printf("%s\n",my_line->contents); printf("sizeof struct line = %lu\n", sizeof (struct line));printf("address struct line = %p\n", my_line);printf("address of char contents[0] = %p\n", &my_line->contents);
}
输出结果是:
hello
sizeof struct line = 2
address struct line = 0x8c8010
address of char contents[0] = 0x8c8012
注意:
- struct line 的大小是 2 个字节,说明零长数组 contents 确实不占用空间
- contents 数组的起始地址就在 short len 的后面;原因是数组的类型是 char,如果改成 int ,那么在 short len 的后面就有填充
- 我们可以通过结构体成员 contents 访问内存(代码 17-18 行)。contents 就好比是一个标签,代表着某个地址常量
- malloc 只调用了一次(第 15 行)
结合这个例子,零长数组的好处是,可以根据需要给 struct line
分配空间,
struct line *my_line = (struct line *) malloc (sizeof (struct line) + my_len);
想用多少,就追加多少。
零长数组和指针的区别
有人说,用指针也可以实现。比如
struct line {short len;void *contents;
};
其实是有区别的:
- void *contents 是一个变量,本身是占用内存的
- 在使用的时候,contents 指向另外一块内存,也就是说还要调用一次 malloc
- contents 指向的内存和 struct line 占用的内存一般是不连续的
所以,零长数组的优势就体现出来了。
定义什么类型的零长数组
有人认为,结构体尾部的零长数组应该是 char 类型,好处是节省空间,不需要在它前面填充。其实不然,具体是什么类型根据应用来定。
比如 Linux 内核里面有个结构体——USB request block
struct urb {struct kref kref;void *hcpriv;atomic_t use_count;atomic_t reject;int unlinked;...int error_count;void *context;usb_complete_t complete;struct usb_iso_packet_descriptor iso_frame_desc[0];
};
11:它使用的零长数组是 struct usb_iso_packet_descriptor
类型,而不是 char 类型。
参考资料
嵌入式C语言自我修养 05:零长度数组 - 知乎
GNU C 中的零长数组相关推荐
- GNU C中的零长度数组
http://blog.csdn.net/ssdsafsdsd/article/details/8234736 在标准C和C++中,长度为0的数组是被禁止使用的.不过在GNU C中,存在一个非常奇怪的 ...
- (转载)C语言的零长数组
(转载)http://www.cnblogs.com/sunyubo/archive/2012/07/04/2708241.html 在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 i ...
- GNU Radio中的消息传递机制(Message Passing)
目录 0.首先看下 GR 中一些常用术语的官方解释 1.定义理解 2.消息传递端口API 3.消息处理函数 4.通过流程图连接消息 5.从外部源发布数据 6.使用消息传送命令 7.一个消息传输的例子 ...
- 【CV】Numpy|Python中矩阵和数组乘法及向量相关问题
在numpy中 一维数组不是向量,但可以通过reshape转换成行向量或者列向量 Numpy库学习--向量表示_o_Eagle_o-CSDN博客 一维数组左乘矩阵时,把数组看做行向量 一维数组右乘矩阵 ...
- python slice是共享内存吗_在共享内存中使用numpy数组进行多处理
在共享内存中使用numpy数组进行多处理 我希望在共享内存中使用numpy数组,以便与多处理模块一起使用.困难之处在于它像一个numpy数组一样使用,而不仅仅是作为一个ctype数组使用.from m ...
- Java中创建泛型数组
Java中创建泛型数组 使用泛型时,我想很多人肯定尝试过如下的代码,去创建一个泛型数组 T[] array = new T[]; 当我们写出这样的代码时编译器会报Cannot create a gen ...
- 求二维数组中最大子数组的和
任国庆 张博 之前我们讨论了在一维数组中求最大子数组的和,在此基础上我们开始讨论二维数组的最大子数组. 求二维数组的最大子数组思想是建立在以为数组.首先将数组的第一列看成一个一维数组,找到该列的最大 ...
- js中对arry数组的各种操作小结
最近工作比较轻松,于是就花时间从头到尾的对js进行了详细的学习和复习,在看书的过程中,发现自己平时在做项目的过程中有很多地方想得不过全面,写的不够合理,所以说啊,为了在以后的工作中写出最优化的代码,我 ...
- 如何在 bash 中使用索引数组
数组是一种数据结构,表示具有相同数据类型的对象集合.bash shell中支持两种类型的数组:关联数组或索引数组.在本文中,将演示如何在 bash 中使用索引数组.以下使用 shell 示例来说明索引 ...
最新文章
- 【C++】C++好书推荐
- CSDN 中秋节日礼品盒 | 中秋节快乐
- SolrJ查询Solr数据
- 预训练模型参数重载必备!
- trace--求矩阵的迹
- activemq启动异常
- php实现标签云,php标签云的实现代码
- AI 六十年,强人工智能何时到来?
- Codeforces-691C-Exponential notation(模拟)Java 以及输入的处理
- Unity3d之HashSlash学习笔记(一)--角色属性类的构架
- CHIP-seq 分析笔记
- Redis反序列化错误Could not read JSON: Cannot construct instance of `java.util.ArrayList$SubList`
- thinkpad x60安装WINDOWS2003SERVER
- 微信公众号开发之配置开发服务器
- Day-4 三国演义目录爬取,requests请求,bs4数据分析的应用
- thinkphp使用migration/Seeder
- 《高等数学》 总结 导数、微分、不定积分
- 腾讯副总裁曾宇:谈谈腾讯的技术价值观与技术人才修炼
- 投资理财-一个以投资为职业的人
- VSCode 的安装与配置