嵌套结构初始化取决于范围?

时间:2014-05-29 20:12:35

标签: c struct initialization

我无法弄清楚这一点。为什么编译:

typedef struct A {
    int foo[3];
} a_t;

typedef struct B {
    char tag;
    a_t foo;
} b_t;

const a_t default_a = { { 1, 2, 3 } };

int
main(int argc, char **argv)
{
    const b_t default_b = { 'A', default_a };
    return 0;
}

这不是:

typedef struct A {
    int foo[3];
} a_t;

typedef struct B {
    char tag;
    a_t foo;
} b_t;

const a_t default_a = { { 1, 2, 3 } };

const b_t default_b = { 'A', default_a };

int
main(int argc, char **argv)
{
    return 0;
}


> gcc tp.c
tp.c:13:1 error: initializer element is not constant
tp.c:31:1 error: (near initialization for ...default_b.foo...)

唯一的变化是default_b声明的范围。为什么会有所不同?据我所知,要么它们都是有效的,要么都是错的。但是gcc(v4.7.3)接受第一个而不是第二个。这让我疯了。

[[edit]]奖励积分的后续问题:鉴于第二个程序不符合C标准,我如何以符合标准的方式完成同样的事情? IE:default_b的全局常量定义,包括default_a的值。

1 个答案:

答案 0 :(得分:4)

C语言规范要求使用常量表达式初始化具有静态存储持续时间的对象。

在您的第一个代码段中,default_b具有自动存储持续时间,而在第二个代码段中,由于它在文件范围内定义,因此具有静态存储持续时间。所以第二个程序违反了规则:

C11,6.7.9初始化

  

初始化程序中具有静态或。的对象的所有表达式   线程存储持续时间应为常量表达式或字符串   文字。

限定符const 表示它是常量表达式,而应该将其视为只读。常量表达式可以在编译时进行评估:

6.6常量表达式

  

可以在翻译期间评估常量表达式而不是   运行时,因此可以在常量可以使用的任何地方使用   是