为什么我无法检索灵活的阵列成员大小?

AnA*_*ons 4 c arrays sizeof language-lawyer c11

好的,所以我正在阅读标准论文(ISO C11)的部分,它解释了灵活的阵列成员(见6.7.2.1 p18).它说:

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型; 这被称为灵活的阵列成员.在大多数情况下,将忽略灵活数组成员.特别地,结构的尺寸好像省略了柔性阵列构件,除了它可以具有比省略意味着更多的拖尾填充.但是,当一个.(或 ->)运算符有一个左操作数(指向一个具有灵活数组成员的结构)和右操作数命名该成员时, 它的行为就好像该成员被替换为最长的数组(具有相同的元素类型)不会使结构大于被访问的对象 ; 数组的偏移量应保持为灵活数组成员的偏移量,即使这与替换数组的偏移量不同.如果此数组没有元素,则其行为就好像它有一个元素,但如果尝试访问该元素或生成一个超过它的指针,则行为是未定义的.

以下是一些例子(p20):

例2声明后:


     struct s { int n; double d[]; };
Run Code Online (Sandbox Code Playgroud) 结构struct具有灵活的数组成员d.使用它的典型方法是:

     int m = /* some value */;

struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
Run Code Online (Sandbox Code Playgroud) 并且假设对malloc的调用成功,p指向的对象在大多数情况下表现得好像p已被声明为:

     struct { int n; double d[m]; } *p;
Run Code Online (Sandbox Code Playgroud) (在某些情况下,这种等价性被破坏;特别是,成员d的偏移量可能不同).

添加剧透作为标准内部的示例不是文档.

现在我的例子(从标准中扩展一个):

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    struct s { int n; double d[]; };

    int m = 7;

    struct s *p = malloc(sizeof (struct s) + sizeof (double [m])); //create our object

    printf("%zu", sizeof(p->d)); //retrieve the size of the flexible array member

    free(p); //free out object
}
Run Code Online (Sandbox Code Playgroud)

在线示例.

现在编译器抱怨说p->d类型不完整double[],根据标准文件显然不是这种情况.这是GCC编译器中的错误吗?

chu*_*ica 5

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型 ; ...... C11dr 6.7.2.1 18

以下d是不完整的类型.

struct s { int n; double d[]; };
Run Code Online (Sandbox Code Playgroud)

sizeof运算符应用于具有函数类型或不完整类型的表达式...C11dr§6.5.3.41

// This does not change the type of field `m`.
// It (that is `d`) behaves like a `double d[m]`, but it is still an incomplete type.
struct s *p = foo();

// UB
printf("%zu", sizeof(p->d));
Run Code Online (Sandbox Code Playgroud)