【发布时间】:2019-05-13 20:54:40
【问题描述】:
考虑以下示例:
typedef struct test_flex_arr{
size_t sz;
struct {
int i;
const char *path;
} info[];
} tfa;
int main(void){
size_t sz = 100;
tfa *ptr = malloc(sizeof *ptr + sizeof (*((tfa*) NULL)).info[sz]);
ptr->info[99].i = 10;
printf("%d\n", ptr->info[99].i); //prints 10
}
我预计这个程序会崩溃,但它运行得很好。如指定6.5.3.4(p2):
sizeof运算符产生其操作数的大小(以字节为单位),即 可以是表达式或类型的括号名称。尺寸是 由操作数的类型决定。结果是一个整数。 如果 操作数的类型是变长数组类型,操作数 被评估;否则,不计算操作数并且结果 是一个整数常量
sizeof ((*((tfa*) NULL)).info)[sz] 的操作数类型是变长数组,所以应该计算操作数。但是对操作数的评估意味着取消引用NULL,我预计这会导致崩溃。
代码的行为是否定义良好?
【问题讨论】:
-
这里的括号太多,但看起来 sizeof-ed 表达式不是弹性数组,而是它的元素之一。
-
引用提到 VLA 不是灵活的数组。
-
你应该使用
sz * sizeof(ptr->info) -
是的,看起来是这样。
....info[sz]是数组的一个元素,而不是数组本身。 -
由内而外 :)
((tfa*) NULL)的类型为tfa*。(*((tfa*) NULL))的类型为tfa。这整件事.info是你的数组。并且添加[sz]正在对其进行索引。
标签: c language-lawyer flexible-array-member