未命名结构的灵活数组成员
Flexible array member of unnamed struct
考虑以下示例:
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
的事实不会导致未定义的行为。它只是 returns 数组元素的大小,它不依赖于数组的位置或索引。这就是为什么它在没有警告的情况下编译并且不会崩溃的原因。
但这并没有产生预期的结果。您只会获得数组中一个元素的大小,而不是您实际需要为其分配 space 的 sz
元素。您需要将元素的大小乘以元素的数量。所以使用
tfa *ptr = malloc(sizeof *ptr + sz * sizeof ptr->info[0]);
考虑以下示例:
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
的事实不会导致未定义的行为。它只是 returns 数组元素的大小,它不依赖于数组的位置或索引。这就是为什么它在没有警告的情况下编译并且不会崩溃的原因。
但这并没有产生预期的结果。您只会获得数组中一个元素的大小,而不是您实际需要为其分配 space 的 sz
元素。您需要将元素的大小乘以元素的数量。所以使用
tfa *ptr = malloc(sizeof *ptr + sz * sizeof ptr->info[0]);