简体   繁体   English

LCC:初始化含有结构的结构?

[英]LCC: Initializing Structs Containing Structs?

The following code snippet compiles just fine on Mac OS X with gcc, but fails to compile on Windows with lcc-win32: 以下代码片段在Mac OS X上使用gcc编译得很好,但无法在Windows上使用lcc-win32进行编译:

typedef struct Foo Foo;
typedef struct Bar Bar;

struct Bar { int age; int height; };
struct Foo { Bar barOne; Bar barTwo; };

// Elsewhere, in some function:

Bar barOne = { 2, 4 };
Bar barTwo = { 6, 8 };
Foo instance = { barOne, barTwo };

And gives this error: 并给出了这个错误:

found 'struct Bar' expected 'int' 发现'struct Bar'需要'int'

I can 'overcome' this by initializing the struct this way: 我可以通过这种方式初始化结构来“克服”这个:

Foo instance = { barOne.age, barOne.height, barTwo.age, barTwo.height };

So, I understand what's going on... but I feel like this makes my code a lot more complex (I need to understand the implementation and layout of the other structs I'm using, instead of simply consuming them - and if that layout changes, I have to spider that change out to anyone else using the struct). 所以,我理解发生了什么...但我觉得这会使我的代码变得更复杂(我需要理解我正在使用的其他结构的实现和布局,而不是简单地消耗它们 - 如果这样的布局变化,我必须使用结构转换给任何其他人。

I'm wondering if LCC is being either "more strict" (adhering to some standard) or "more dumb" (the compiler is too dumb to handle this situation). 我想知道LCC是“更严格”(坚持某种标准)还是“更愚蠢”(编译器太愚蠢无法处理这种情况)。

Thanks. 谢谢。

Also, please see my other LCC-Win32 question: LCC: Forward Declaration of Typedef'd Enum Failing? 另外,请参阅我的其他LCC-Win32问题: LCC:Typedef'd Enum的前向声明失败?

As written: 正如所写:

typedef struct Foo Foo;
typedef struct Bar Bar;

struct Foo { Bar barOne; Bar barTwo; };
struct Bar { int age, int height };

// Elsewhere, in some function:

Bar barOne = { 2, 4 };
Bar barTwo = { 6, 8 };
Foo instance = { barOne, barTwo };

the code should fail to compile everywhere (and specifically fails on MacOS X 10.7.1 with GCC 4.6.0) with these errors (plus some others): 代码应该无法在任何地方编译(特别是在带有GCC 4.6.0的MacOS X 10.7.1上失败)以及这些错误(以及其他一些错误):

xx.c:4: error: field ‘barOne’ has incomplete type
xx.c:4: error: field ‘barTwo’ has incomplete type

This is because you try to use Bar before it is defined. 这是因为您在定义之前尝试使用Bar Reverse the order of the structure definitions, and fix the syntax errors in Bar (comma should be semi-colon; missing semi-colon), and then (finally) it does compile on MacOS X. 颠倒结构定义的顺序,并修复Bar中的语法错误(逗号应该是分号;缺少分号),然后(最后)它在MacOS X上编译。

What does the standard say about using structures as initializers? 标准对使用结构作为初始化器有何看法?

§6.7.8 Initialization §6.7.8初始化

¶13 The initializer for a structure or union object that has automatic storage duration shall be either an initializer list as described below, or a single expression that has compatible structure or union type. ¶13具有自动存储持续时间的结构或联合对象的初始化程序应该是如下所述的初始化程序列表,或者是具有兼容结构或联合类型的单个表达式。 In the latter case, the initial value of the object, including unnamed members, is that of the expression. 在后一种情况下,对象的初始值(包括未命名的成员)是表达式的初始值。

Consider the context of a function (this code compiles OK with GCC set fussy): 考虑一个函数的上下文(这段代码可以用GCC设置繁琐编译):

typedef struct Foo Foo;
typedef struct Bar Bar;

struct Bar { int age; int height; };
struct Foo { Bar barOne; Bar barTwo; };

void somefunction(void)
{
    Bar barOne = { 2, 4 };
    Bar barTwo = { 6, 8 };
    Foo instance = { barOne, barTwo };
}

Superficially, it looks to me like barOne and barTwo are not single expressions. 从表面上看,它看起来像barOnebarTwo两个不是单个表达式。 However, the standard goes on to say: 但是,标准继续说:

¶16 Otherwise, the initializer for an object that has aggregate or union type shall be a brace-enclosed list of initializers for the elements or named members. ¶16否则,具有聚合或联合类型的对象的初始值设定项应该是元素或命名成员的大括号括起来的初始值设定项列表。

If the aggregates had to be enclosed braces, then writing this would work: 如果聚合必须是括号,那么写这个将起作用:

Foo instance = { { barOne }, { barTwo } };

GCC emphatically rejects this construct, though. 但是,海湾合作委员会强烈反对这种结构。

i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)

/usr/bin/gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -c xx.c
xx.c:8: warning: no previous prototype for ‘somefunction’
xx.c: In function ‘somefunction’:
xx.c:11: error: incompatible types in initialization
xx.c:11: warning: missing initializer
xx.c:11: warning: (near initialization for ‘instance.barOne.age’)
xx.c:11: error: incompatible types in initialization
xx.c:11: warning: missing initializer
xx.c:11: warning: (near initialization for ‘instance.barTwo.age’)
xx.c:11: warning: missing initializer
xx.c:11: warning: (near initialization for ‘instance.barOne’)
xx.c:11: warning: unused variable ‘instance’

On the whole, I'm inclined to trust GCC's judgement and point the finger at LCC not handling a case validly. 总的来说,我倾向于相信海湾合作委员会的判断,并指责LCC没有有效处理案件。 Disputing that will require a complete parsing of §6.7.8 of the C standard, and I've not provided all the material (it goes to ¶23 before starting on the examples). 争论需要完整解析C标准的§6.7.8,并且我没有提供所有的材料(在开始示例之前它会进入¶23)。

Well it's not called the Little C Compiler sometimes for nothing. 好吧,它有时候什么都不称为Little C Compiler。 It can handle most things but to save space and time it will generally be stricter in these cases. 它可以处理大多数事情,但为了节省空间和时间,在这些情况下通常会更严格。 Implementing something that looks simple usually isn't in a compiler. 实现看起来很简单的东西通常不在编译器中。 Either that or LCC was just never updated to handle these situations. 无论是LCC还是LCC都没有更新来处理这些情况。 Is there a specific reason for using LCC instead of Borland, MSVC++, Cygin/MingW32 gcc? 是否有使用LCC而不是Borland,MSVC ++,Cygin / MingW32 gcc的特定原因?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM