在C语言中,我能否使用指向不完整类型的数组指针?

8

IAR嵌入式C编译器对此非常满意,我认为这是正确的C代码:

struct incomplete;
typedef struct incomplete (*why_not)[2];
struct incomplete {struct incomplete *known_to_work;} array[2];
why_not ok = &array;

然而,gcc和clang对why_not的定义无法处理:

incomplete.c:2:29: error: array type has incomplete element typestruct incomplete’
 typedef struct incomplete (*why_not)[2];
                             ^

从技术上讲,没有理由拒绝“指向不完整数组”的类型定义。毕竟,只有在解除引用这样的变量或执行一些指针算术时才需要结构定义。

我很渴望尽可能隐藏结构定义。

C标准对此有何规定?


在任何情况下(甚至是函数参数),您都不能使用“不完整类型的数组”类型。 - M.M
@M.M 实际上,为什么不呢? - not-a-user
向IAR提交错误报告。像这样的垃圾就是我不使用他们编译器的原因。他们竟然要求你付钱才能获得修复他们不合规的漏洞。这尤其令人尴尬,因为C语言的这部分自上世纪80年代以来就一直存在。 - Lundin
由于标准规定如此,@not-a-user - M.M
我使用IAR ARM编译器进行了测试,只有在启用严格模式时才会收到警告。 - user694733
1
这在C语言中也是一个约束违规,原因相同:struct S; void f(struct S s[]);,即使 void f(struct S *s); 是正确的,而且如果S是完整的话两者等价。 - M.M
2个回答

8
代码使用了一个元素类型不完整的数组声明符。根据6.7.6.2/1数组声明符,这违反了ISO C中的约束规定:

约束条件

除了可选的类型限定符和关键字static之外,[]还可以包含表达式或*。如果它们包含一个表达式(指定数组大小),则该表达式必须具有整数类型。如果表达式是一个常量表达式,则其值应大于零。元素类型不能是不完整或函数类型。


6
以下陈述:
typedef struct incomplete (*why_not)[2];

这是一个指向包含两个struct incomplete的数组的指针。由于struct incomplete尚未定义,编译器不知道其大小。

但是,以下内容将起作用:

typedef struct incomplete *why_not[2];

即:一个指向struct incomplete结构体的指针数组。编译器确实知道不完整类型的指针大小(即仅需要存储地址的大小)。
编辑: 在两种情况下,编译器都不需要知道struct incomplete的大小(只要没有进行指针运算),因为两个声明仅仅是在声明指针。

2
编译器同样知道不完整类型的数组指针的大小,这也只是一个地址。正如我所指出的,至少有一个编译器可以接受这种情况。问题是,标准(C99或C11)怎么说? - not-a-user
不同类型对象的地址大小可能不同(例如,int * 可能是2字节,而 void * 则是3字节)。 - M.M
@M.M,在这种情况下,应该是 编译器始终知道不完整类型的指针大小 - JFMR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接