Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1863410
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2388
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(184)

文章存档

2021年(26)

2020年(56)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: C/C++

2019-11-29 13:39:36

之前在写redis当中的sds结构的时候,留了个坑,不晓得为啥人家sds头的结构体最后面有一个0长度的数组,文章链接在这里http://blog.chinaunix.net/uid-31422160-id-5795408.html

最近看linux内核代码的时候,发现内核当中有些链表也搞这一套,发现事情并不简单,于是痛定思痛,自己挖的坑,自己要填上,在网上找啊找啊找,终于找到了官方文档,这里自己翻译,权当给自己长点记性,英语比较不错的读者可以移步至:

0长数组实际上是一个gcc当中的一个扩展功能,它可以如下声明,但是其中的contents却不占用结构体的存储空间,而是指向紧挨着结构体的下一个字节

点击(此处)折叠或打开

  1. struct line {
  2.   int length;
  3.   char contents[0];
  4. };

这里需要注意的是,0长数组只有定义在结构体的最后才会有用~
如果按照如下定义一个struct line结构, thisline->contents就指向了结构体后的首个字节


点击(此处)折叠或打开

  1. struct line *thisline = (struct line *)
  2.   malloc (sizeof (struct line) + this_length);
  3. thisline->length = this_length;
由于gcc允许静态初始化这种结构,所以当遇见来回嵌套的情况,编译器不会懵x,但是多的话,看得人就会懵x了,比如下边这个还好的


点击(此处)折叠或打开

  1. struct f1 {
  2.   int x; int y[];
  3. } f1 = { 1, { 2, 3, 4 } };

  4. struct f2 {
  5.   struct f1 f1; int data[3];
  6. } f2 = { { 1 }, { 2, 3, 4 } };

这样就会带来一个问题,就是嵌套的时候,如果里面的结构体有这种定义的非空扩展,如果对其进行修改,实际上会修改到上层结构的地址当中,造成各种各样不愿意发生的事情,所以gcc就不允许在使用这种扩展功能区静态初始化非顶端结构,比如下面:

点击(此处)折叠或打开

  1. struct foo { int x; int y[]; };
  2. struct bar { struct foo z; };

  3. struct foo a = { 1, { 2, 3, 4 } }; // Valid. a是顶端结构
  4. struct bar b = { { 1, { 2, 3, 4 } } }; // Invalid. b里面的2,3,4是非顶端结构,且使用该扩展
  5. struct bar c = { { 1, { } } }; // Valid. 虽然c里面的结构是扩展功能,但是其为空,所以允许
  6. struct foo d[1] = { { 1, { 2, 3, 4 } } }; // Invalid. d表示一个数组,非顶端结构

阅读(312276) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~