我很好奇以下代码片段为什么不编译:
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
实际上不是编译器的根本原因时间常数。谢谢
最佳答案
它主要与初始化有关。
初始化后的变量通常不会通过“将这个值放到该位置”的代码来初始化,而是通过加载特定值范围(即.data
resp)的定义来初始化。 .rodata
段,到应该位于的内存位置。这是由OS文件加载器完成的。 (严格来说,这不是C的属性,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
的组件。