使用其他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语言中, const
或static const
值不被视为“编译时间常量”,而
#define FooZero {0, 0}
被认为是编译时常量。 你可能会说“但是,它甚至会说const
!它怎么能不是常数?” 实际上语言表示你不能改变你指定为const
的东西的值,但你也不能将它用作初始化器。 你可以问为什么你喜欢它,它不会改变语言定义它的方式 – 尽管你的编译器可能会给你一个改变这种行为的选项,并且在任何情况下都不是很难解决。
我认为C编译器很常见的是处理像全局变量这样的静态常量 – 也就是说,实际为变量分配空间(永远不会改变),而不是将硬值编程到机器代码中,就像你做的那样#define
。 在这种情况下,正如编译器所说的那样, 常量不是编译时常量 ,尽管它们在初始化之后(在运行时)是所有其他目的的常量。