【问题标题】:Initializing Const Struct with other Const Struct Instances使用其他 Const Struct 实例初始化 Const Struct
【发布时间】:2011-09-12 04:57:31
【问题描述】:

我很好奇为什么下面的代码 sn-p 不能编译:

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 } - 我提出问题的目的不是如何解决问题 - 我试图了解 @987654329 的根本原因@ 实际上不是编译时常量。

谢谢

【问题讨论】:

  • stackoverflow.com/questions/3025050/… 是一个很好的解释,封装了我要写的内容
  • @Foo Bah - 感谢您的链接。然而;我的问题是“为什么会这样”。我觉得你引用的问题的答案并没有真正回答我“为什么”的问题——他们只是指出了我已经知道的情况。
  • @Steve 如果不使用 C 中的函数,您就无法解决问题吗? FooZero 也不是编译时间常数。两个链接都是这么说的。
  • @Pavan; Also FooZero is not compile time constant. 是的,我知道了。我的问题是为什么会这样?为什么语言的机制是这样的?

标签: c struct initialization


【解决方案1】:

主要和初始化有关。

初始化的变量通常不是由“把这个值放到那个位置”的代码初始化的,而是通过一个加载特定值范围的定义来初始化的,.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->a)访问BarZero.foo 的组件,

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

【讨论】:

  • 感谢您对初始化的评论。这就是我一直在寻找的。关于您对指针的评论 - 理解 - 但是我需要在每次分配期间“复制”整个结构......所以在这种情况下,有一个指向另一个结构的指针不是我想要的 - 如果有人在某个地方改变了指向的结构中的值,它会破坏系统。但点很好。谢谢!
  • 因为它们都被声明为const,所以(通常)没有人应该能够修改它。
【解决方案2】:

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

#define FooZero  {0, 0}

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

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

【讨论】:

  • 感谢您的回复! --- You can ask why all you like, it won't change how the language defines it. 是的,但我可能会被这个答案所启发。 --- although they are constants for all other purposes after they are initialised (at runtime). 有趣。它们是什么时候被初始化的?第一次使用时? --- 另外,感谢#define 指针。
  • @Steve 感谢您的评论-我认为glglgl已经很好地回答了您有关初始化的问题-在启动时将数据加载到程序中时会发生初始化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 2020-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多