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

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

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的使用 – 我的目的是问问题不是如何解决问题 – 我试图理解FooZero不是的根本原因,事实上,编译时常量。

谢谢

它主要与初始化有关。

初始化变量通常不会被代码说明“将此值放到该位置”,而是通过加载特定值范围的定义, .data resp。 .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->a )访问BarZero.foo的组件,

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

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

 #define FooZero {0, 0} 

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

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