考虑以下示例:
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)
:
The
sizeof
operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant
sizeof ((*((tfa*) NULL)).info)[sz]
的操作数类型是可变长度数组,因此应对操作数求值。但是对操作数的求值意味着取消引用 NULL
,我预计这会导致崩溃。
代码的行为是否定义明确?
最佳答案
(*((tfa*) NULL)).info[sz]
不是变长数组类型,因为(*((tfa*) NULL)).info
不是类型。
因此它将其视为普通表达式,引用数组 (*((tfa*) NULL)).info
的 sz
元素。根据引用的规范,这不会被评估,因此它取消引用 NULL
的事实不会导致未定义的行为。它只是返回数组元素的大小,这与数组的位置或索引无关。这就是为什么它在没有警告的情况下编译并且不会崩溃的原因。
但这不会产生预期的结果。您只会获得数组中一个元素的大小,而不是您实际需要为其分配空间的 sz
元素。您需要将元素的大小乘以元素的数量。所以用
tfa *ptr = malloc(sizeof *ptr + sz * sizeof ptr->info[0]);
关于c - 未命名结构的灵活数组成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56119744/