我很好奇以下代码片段为什么不编译:

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的组件。

09-12 13:13