尝试使用const初始化variables时出错“初始化元素不是常量”

我得到以下程序的第6行(初始化my_foo到foo_init)的错误,我不知道为什么。

typedef struct foo_t { int a, b, c; } foo_t; const foo_t foo_init = { 1, 2, 3 }; foo_t my_foo = foo_init; int main() { return 0; } 

请记住,这是我正在处理的一个更大的多文件项目的简化版本。 目标是在目标文件中有一个常量,多个文件可以用来初始化一个状态结构。 由于它是一个资源有限的embedded式目标,结构不是那么小,所以我不想要多个源代码副本。 我不想使用:

 #define foo_init { 1, 2, 3 } 

我也想写可移植的代码,所以我需要一个有效的C89或C99的解决scheme。

这是否与目标文件中的ORG有关? 初始化variables进入一个ORG并通过复制第二个ORG的内容来初始化?

也许我只需要改变我的策略,并有一个初始化函数在启动时做所有的副本。 除非有其他的想法吗?

在C语言中,具有静态存储持续时间的对象必须用常量expression式或包含常量expression式的聚合初始化器进行初始化。

即使对象声明为const ,一个“大”对象也不会是C中的常量expression式。

此外,在C语言中,术语“常量”是指文字常量 (如1'a'0xFF等等)和枚举成员。 C语言术语中的常量限定对象(任何types) 不是常量 。 它们不能用于具有静态存储时间的对象的初始化程序,而不pipe它们的types如何。

例如,这不是一个常数

 const int N = 5; /* `N` is not a constant in C */ 

上面的N在C ++中是一个常量,但是它不是C中的一个常量。所以,如果你尝试的话

 static int j = N; /* ERROR */ 

你会得到相同的错误:尝试用非常量初始化一个静态对象。

这就是为什么在C语言中,我们主要使用#define来声明命名常量,并且还使用#define来创build命名的聚合初始化程序。

这是语言的限制。 在6.7.8 / 4节中:

具有静态存储持续时间的对象的初始化器中的所有expression式应该是常量expression式或string文字。

在6.6节中,规范定义了必须考虑的常数expression式。 没有它声明constvariables必须被认为是一个常量expression式。 编译器扩展它是合法的( 6.6/10 - An implementation may accept other forms of constant expressions ),但是会限制可移植性。

如果你可以改变my_foo所以它没有静态存储,你会没事的:

 int main() { foo_t my_foo = foo_init; return 0; } 

只是为了说明比较和对比代码是从http://www.geeksforgeeks.org/g-fact-80/ / 代码在gcc中失败并通过g ++ /

  #include<stdio.h> int initializer(void) { return 50; } int main() { int j; for (j=0;j<10;j++) { static int i = initializer(); /*The variable i is only initialized to one*/ printf(" value of i = %d ", i); i++; } return 0; } 

这有点旧了,但是我遇到了类似的问题。 如果你使用一个指针,你可以这样做:

 #include <stdio.h> typedef struct foo_t { int a; int b; int c; } foo_t; static const foo_t s_FooInit = { .a=1, .b=2, .c=3 }; // or a pointer static const foo_t *const s_pFooInit = (&(const foo_t){ .a=2, .b=4, .c=6 }); int main (int argc, char **argv) { const foo_t *const f1 = &s_FooInit; const foo_t *const f2 = s_pFooInit; printf("Foo1 = %d, %d, %d\n", f1->a, f1->b, f1->c); printf("Foo2 = %d, %d, %d\n", f2->a, f2->b, f2->c); return 0; }