使用其他Const Struct实例初始化Const Struct

时间:2011-09-12 04:57:32

标签: c struct initialization

我很好奇为什么下面的代码片段无法编译:

typedef struct Foo {
    int a;
    int b;
} Foo;

static const Foo FooZero = { 0, 0 };

typedef struct Bar {
    Foo foo;
    int c;
} Bar;

static const Bar BarZero = { FooZero, 0 };

它抱怨使用了FooZero,声称FooZero不是Compile-Time Constant

但不是吗?我在这里不理解什么?

显然,我可以简单地用FooZero替换初始化程序中{ 0, 0 }的使用 - 我的目的是问问题不是如何解决问题 - 我试图理解底层FooZero实际上不是编译时常量的原因。

由于

2 个答案:

答案 0 :(得分:10)

它主要与初始化有关。

初始化变量通常不会被“将此值放到该位置”的代码初始化,而是通过加载特定值范围的定义.data来初始化。 .rodata段,到应该是它的内存位置。这是由OS文件加载器完成的。 (严格来说,这不是C的属性,它对此不了解,而是对执行环境一无所知。)

也就是说,不可能将该存储区的一部分从另一个存储区复制。但是,编译器本身可能会识别声明的意图并将相同的值放到不同的位置。但这可能太过“猜测”了。

在你的情况下:指向FooZero的指针不是更好的解决方案吗?值都是相同的......

typedef struct Foo {
    int a;
    int b;
} Foo;

static const Foo FooZero = { 0, 0 };

typedef struct Bar {
    Foo * foo;
    int c;
} Bar;

static const Bar BarZero = { &FooZero, 0 };

或者相反:

typedef struct Foo {
    int a;
    int b;
} Foo;

typedef struct Bar {
    Foo foo;
    int c;
} Bar;

static const Bar BarZero = { { 0, 0 }, 0 };
static const Foo * FooZero = &BarZero.foo; // if that is possible, untested...

在第一种情况下,您必须使用BarZero.foo访问->的组件(例如BarZero.foo->a),

在第二种情况下,您必须使用FooZero访问->的组件(例如FooZero->a)。

答案 1 :(得分:1)

在C语言中,conststatic const值不被视为“编译时常量”,而

#define FooZero  {0, 0}

被认为是编译时常量。你可能会说“但是,它甚至会说 const !它怎么能不是常数?”实际上,该语言表示您无法将指定的事物的值更改为const,但您也无法将其用作初始值设定项。你可以问为什么你喜欢它,它不会改变语言定义它的方式 - 虽然你的编译器可能会给你一个改变这种行为的选项,并且在任何情况下都不是很难解决。

我认为C编译器将静态常量视为全局变量是很常见的 - 也就是说,实际为变量(永远不会改变)分配空间,而不是将硬值编程到机器代码中。你做了#define。在这种情况下,常量,实际上正如编译器所说,不是编译时常量,尽管它们在初始化之后(在运行时)是所有其他目的的常量。