我对 SDCC 有疑问。 我的代码(我试图从另一个编译器移植)使用具有灵活数组成员的结构。 但是,当我尝试编译以下代码时:
/** header of string list */
typedef struct {
int nCount;
int nMemUsed;
int nMemAvail;
} STRLIST_HEADER;
/** string list entry data type */
typedef struct {
int nLen;
char str[];
} STRLIST_ENTRY;
/** string list data type */
typedef struct {
STRLIST_HEADER header;
STRLIST_ENTRY entry[];
} STRLIST; // By the way, this is the line the error refers to.
int main()
{
return 0;
}
SDCC 给出以下错误:
$ sdcc -mz80 -S --std-c99 test.c
test.c:18: warning 186: invalid use of structure with flexible array member
test.c:18: error 200: field 'entry' has incomplete type
什么给予? 这段代码在 gcc 中编译得很好,更不用说我正在使用的其他 z80 编译器了。
编辑:我发现这个 SDCC bug 这似乎是相关的。 有人可以解释一下是否是以及如何吗?
SDCC 就在那里,gcc-4.6.2 也不能“很好”地编译它。好吧,如果你要求它迂腐地遵守标准。
使用
-std=c99 -pedantic
(或 -std=c1x -pedantic
)编译,gcc 发出
warning: invalid use of structure with flexible array member
和 clang-3.0 的行为类似,它的警告信息稍微丰富一些:
warning: 'STRLIST_ENTRY' may not be used as an array element due to flexible array member
标准6.7.2.1(3)中禁止:
结构或联合不应包含不完整或函数类型的成员(因此,结构不应包含其自身的实例,但可以包含指向其自身实例的指针),除非结构的最后一个成员具有更多类型超过一个命名成员可能具有不完整的数组类型; 此类结构(以及可能递归地包含此类结构成员的任何联合)不应是结构的成员或数组的元素。
(重点是我的)
gcc 和 clang 允许将具有灵活数组成员的
struct
作为 struct
的成员或作为扩展的数组。该标准禁止这样做,因此使用它的代码不可移植,并且每个编译器都有权拒绝该代码。
链接的问题不相关,它是关于如果将具有灵活数组成员的
struct
实例化为自动数组,则不发出警告,这是标准不允许的(但被 SDCC 和其他人接受作为扩展) .
思考为什么这是一个错误。
STRLIST_ENTRY 的大小未知,因为 str[] 是可变长度。
STRLIST 包含 STRLIST_ENTRY 的可变长度数组。
在内存中,数组是一系列紧接着一个的STRLIST_ENTRY。
由于其中的元素大小未知,如何知道索引指向的偏移量?
char str[] 应该被赋予固定大小,或者将 char* 转换为数组外部的字符串。
我知道我已经晚了 8 年:),但也许这对其他人有帮助。这是用于结构末尾数据的技巧(即,当您有标头且最后一个成员是未知大小的数据时):
typedef struct {
int nLen;
char str[0];
} STRLIST_ENTRY;
这将允许您使用索引来寻址字符串内的任何字符,即
str[10]
和 char *ptr=str
也将为您提供正确的结果。