考虑以下示例:
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
的引用,我希望这会导致崩溃。
代码的行为定义是否正确?
答案 0 :(得分:8)
(*((tfa*) NULL)).info[sz]
不是可变长度数组类型,因为(*((tfa*) NULL)).info
不是类型。
因此,将其视为普通表达式,引用数组sz
的{{1}}元素。根据引用的规范,不会对此进行评估,因此它取消引用(*((tfa*) NULL)).info
的事实不会导致未定义的行为。它仅返回数组元素的大小,而大小与数组或索引的位置无关。这就是为什么它会在没有警告的情况下编译并且不会崩溃的原因。
但这不会产生预期的结果。您只得到数组中一个元素的大小,而不是实际需要为其分配空间的NULL
元素的大小。您需要将元素的大小乘以元素的数量。所以用
sz