As a special case, the last element of a structure with more than one
named member may have an incomplete array type; this is called a
flexible array member. In most situations, the flexible array member
is ignored. In particular, the size of the structure is as if the
flexible array member were omitted except that it may have more
trailing padding than the omission would imply. However, when a.
(or
->
) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member,
it behaves as if that member were replaced with the longest array
(with the same element type) that would not make the structure larger
than the object being accessed; the offset of the array shall remain
that of the flexible array member, even if this would differ from that
of the replacement array. If this array would have no elements, it
behaves as if it had one element but the behavior is undefined if any
attempt is made to access that element or to generate a pointer one
past it.
以下是一些例子(p20):
例2声明后:
struct s { int n; double d[]; };
结构struct具有灵活的数组成员d.一种典型的方式
用这个是:
int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
并假设对malloc的调用成功,该对象指向
对于大多数用途来说,p表示如同p已被声明为:
struct { int n; double d[m]; } *p;
(在某些情况下,这种等同性被打破;在
特别是,成员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 }
在线example.
现在编译器抱怨p-> d具有不完整类型double [],根据标准文件显然不是这种情况.这是GCC编译器中的错误吗?
As a special case, the last element of a structure with more than one named member may have an incomplete array type; … C11dr 6.7.2.1 18
在下面的d是不完整的类型.
struct s { int n; double d[]; };
The sizeof operator shall not be applied to an expression that has function type or an incomplete type … C11dr §6.5.3.4 1
// 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));