c - 未命名结构的灵活数组成员

标签 c language-lawyer flexible-array-member

考虑以下示例:

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
}

DEMO

我预计这个程序会崩溃,但它运行得很好。按照指定 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)).infosz 元素。根据引用的规范,这不会被评估,因此它取消引用 NULL 的事实不会导致未定义的行为。它只是返回数组元素的大小,这与数组的位置或索引无关。这就是为什么它在没有警告的情况下编译并且不会崩溃的原因。

但这不会产生预期的结果。您只会获得数组中一个元素的大小,而不是您实际需要为其分配空间的 sz 元素。您需要将元素的大小乘以元素的数量。所以用

tfa *ptr = malloc(sizeof *ptr + sz * sizeof ptr->info[0]);

关于c - 未命名结构的灵活数组成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56119744/

相关文章:

c - 在 while 循环中平均整数。 C语言

c++ - 自由事件。使用线程支持配置 event_base

c++ - C++结构中的运行时大小的数组

c - 替代灵活数组成员,无需动态内存分配

c - 零元素数组需要什么?

c - 通过 libCurl 发送电子邮件 (C)

c - 将 POSIX 显示为没有 gmtime 和 asctime 的日历日期

c++ - 指针互转换与具有相同地址

c++ - 要插入的值的状态

c++ - 了解构造函数概念