BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #101023同步于 2021/8/3
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

请教一个c/c++问题(关于零长度数组的概念)

dzx1997
2021/8/3镜像同步27 回复
今天碰到了这个“零长度数组的概念”。(2020fall cmu15445的bplustreeinternalpage.h的private底部) 在c.runoob.com/compile/12写了几个小例子,如下: 1.成功 int a[0]; a[0] = 1; a[1] = 2; cout << a[1]; // 成功输出2 2.段错误,最终测试i<3不报错。 int a[0]; for (int i =0; i < 10; i++) { a[i] = i; } cout << a[1]; 第一次接触到这个定义,以为是搞笑的。结果发现我是搞笑的。。。然后很奇怪的是第二个测试例子的if条件貌似有限制。。 刚去stack overflow查到这个叫zero length array,但是进一步查询发现一般是用作struct的hack trick。和我上面的例子也不太符合。 有朋友可以分享下见解嘛?
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
chenxiansf机器人#1 · 2021/8/3
一般放在struct最后一个字段用来动态指定长度的吧,你的例子没分配内存
a912655391机器人#2 · 2021/8/3
C语言里面大多数情况下数组名字都可以看成是指针,编译器也不会对数组越界的代码进行检查,所以代码能编译运行。访问a[n],实际上相当于执行代码*(a+n),所以相当于是对a+n这个地址进行了访问,这个地址可能会在编译器安排的函数栈上,这样的话能顺利访问该地址,但是也有可能不在进程的地址空间内,所以访问的时候就会段错误。 零长度数组的话,应该是在结构体的最后声明一个长度为零的数组,但是在生成结构体实例的时候,还是会使用malloc来多分配一些内存,这样就能方便使用结构体里面的数组名来访问分配到的内存,同时由于数组长度声明为0,所以编译器在分配内存的时候也不会造成浪费,数组名相当于是标记了结构体末尾的地址。
dzx1997机器人#3 · 2021/8/3
但是cmu15445就把他当成动态数组用了,没涉及struct 【 在 chenxiansf 的大作中提到: 】 : 一般放在struct最后一个字段用来动态指定长度的吧,你的例子没分配内存
cppIsNo1机器人#4 · 2021/8/3
所以访问的a[0],a[1]实际都是不正确的吧。只是变量a后面的栈内存没有被使用,你可以修改/读取它的值。可以做个试验 int a[0]; a[0] = 1; a[1] = 2; int b[2]; b[0] = 22; b[1] = 33; std::cout << a[1] << std::endl; 这时候a[1] = 22?
paper777机器人#5 · 2021/8/3
比如一个tlv: struct Header { Type type; size_t length; char data[0]; }; header后直接拼接data的话可以trick地访问data字段,例如 header.data[x]
chenxiansf机器人#6 · 2021/8/3
也可以呀,动态数组不就是长度加头部指针吗 【 在 dzx1997 的大作中提到: 】 : 但是cmu15445就把他当成动态数组用了,没涉及struct
dzx1997机器人#7 · 2021/8/3
但是这个行为不会很危险么?没有指定大小,访问到不该访问的东西,感觉也需要做一些限定吧。 【 在 chenxiansf 的大作中提到: 】 : 也可以呀,动态数组不就是长度加头部指针吗
dzx1997机器人#8 · 2021/8/3
struct的这个trick可以理解,但是cmu15445这个用法不太一样,有空我贴一下真实上下文 【 在 paper777 的大作中提到: 】 : 比如一个tlv: : struct Header { : ............
Nroskill机器人#9 · 2021/8/3
你这个例子不core只是运气好,但是可能会造成栈内存写坏的,并不是说用法没问题。 如果你经常看网络协议的代码就不奇怪了,比如5楼的例子,这里的data是不占内存的。