文章目录

  • 什么是零长数组(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

注意:

  1. struct line 的大小是 2 个字节,说明零长数组 contents 确实不占用空间
  2. contents 数组的起始地址就在 short len 的后面;原因是数组的类型是 char,如果改成 int ,那么在 short len 的后面就有填充
  3. 我们可以通过结构体成员 contents 访问内存(代码 17-18 行)。contents 就好比是一个标签,代表着某个地址常量
  4. malloc 只调用了一次(第 15 行)

结合这个例子,零长数组的好处是,可以根据需要给 struct line 分配空间,

struct line *my_line = (struct line *) malloc (sizeof (struct line) + my_len);

想用多少,就追加多少。

零长数组和指针的区别

有人说,用指针也可以实现。比如

struct line {short len;void *contents;
};

其实是有区别的:

  1. void *contents 是一个变量,本身是占用内存的
  2. 在使用的时候,contents 指向另外一块内存,也就是说还要调用一次 malloc
  3. 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 中的零长数组相关推荐

  1. GNU C中的零长度数组

    http://blog.csdn.net/ssdsafsdsd/article/details/8234736 在标准C和C++中,长度为0的数组是被禁止使用的.不过在GNU C中,存在一个非常奇怪的 ...

  2. (转载)C语言的零长数组

    (转载)http://www.cnblogs.com/sunyubo/archive/2012/07/04/2708241.html  在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 i ...

  3. GNU Radio中的消息传递机制(Message Passing)

    目录 0.首先看下 GR 中一些常用术语的官方解释 1.定义理解 2.消息传递端口API 3.消息处理函数 4.通过流程图连接消息 5.从外部源发布数据 6.使用消息传送命令 7.一个消息传输的例子 ...

  4. 【CV】Numpy|Python中矩阵和数组乘法及向量相关问题

    在numpy中 一维数组不是向量,但可以通过reshape转换成行向量或者列向量 Numpy库学习--向量表示_o_Eagle_o-CSDN博客 一维数组左乘矩阵时,把数组看做行向量 一维数组右乘矩阵 ...

  5. python slice是共享内存吗_在共享内存中使用numpy数组进行多处理

    在共享内存中使用numpy数组进行多处理 我希望在共享内存中使用numpy数组,以便与多处理模块一起使用.困难之处在于它像一个numpy数组一样使用,而不仅仅是作为一个ctype数组使用.from m ...

  6. Java中创建泛型数组

    Java中创建泛型数组 使用泛型时,我想很多人肯定尝试过如下的代码,去创建一个泛型数组 T[] array = new T[]; 当我们写出这样的代码时编译器会报Cannot create a gen ...

  7. 求二维数组中最大子数组的和

    任国庆  张博 之前我们讨论了在一维数组中求最大子数组的和,在此基础上我们开始讨论二维数组的最大子数组. 求二维数组的最大子数组思想是建立在以为数组.首先将数组的第一列看成一个一维数组,找到该列的最大 ...

  8. js中对arry数组的各种操作小结

    最近工作比较轻松,于是就花时间从头到尾的对js进行了详细的学习和复习,在看书的过程中,发现自己平时在做项目的过程中有很多地方想得不过全面,写的不够合理,所以说啊,为了在以后的工作中写出最优化的代码,我 ...

  9. 如何在 bash 中使用索引数组

    数组是一种数据结构,表示具有相同数据类型的对象集合.bash shell中支持两种类型的数组:关联数组或索引数组.在本文中,将演示如何在 bash 中使用索引数组.以下使用 shell 示例来说明索引 ...

最新文章

  1. 【C++】C++好书推荐
  2. CSDN 中秋节日礼品盒 | 中秋节快乐
  3. SolrJ查询Solr数据
  4. 预训练模型参数重载必备!
  5. trace--求矩阵的迹
  6. activemq启动异常
  7. php实现标签云,php标签云的实现代码
  8. AI 六十年,强人工智能何时到来?
  9. Codeforces-691C-Exponential notation(模拟)Java 以及输入的处理
  10. Unity3d之HashSlash学习笔记(一)--角色属性类的构架
  11. CHIP-seq 分析笔记
  12. Redis反序列化错误Could not read JSON: Cannot construct instance of `java.util.ArrayList$SubList`
  13. thinkpad x60安装WINDOWS2003SERVER
  14. 微信公众号开发之配置开发服务器
  15. Day-4 三国演义目录爬取,requests请求,bs4数据分析的应用
  16. thinkphp使用migration/Seeder
  17. 《高等数学》 总结 导数、微分、不定积分
  18. 腾讯副总裁曾宇:谈谈腾讯的技术价值观与技术人才修炼
  19. 投资理财-一个以投资为职业的人
  20. VSCode 的安装与配置

热门文章

  1. 神经网络neural network简单理解
  2. 超越村后端开发(3:安装djangorestframework+序列化+API开发前期准备)
  3. POJ:3579-Median(二分+尺取寻找中位数)
  4. 有关Java中json字符串与map的转换使用
  5. CentOS下Yum使用
  6. OnScrollListener回调分析
  7. struts2配置文件(简单)
  8. 卷积神经网络算法的一个实现
  9. 人生苦短,Let's Go!
  10. 从理论角度理解L1、L2正则化