我在以下程序的第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;
}

请记住,这是我正在进行的一个大型多文件项目的简化版本。目标是在目标文件中有一个常量,多个文件可以使用它来初始化一个状态结构。由于它是一个资源有限的嵌入式目标,而且结构也不是那么小,所以我不想要源的多个副本。我不喜欢使用:

#define foo_init { 1, 2, 3 }

我还试图编写可移植的代码,所以我需要一个有效的C89或C99的解决方案。

这和目标文件中的组织有关系吗?初始化变量进入一个ORG,并通过复制第二个ORG的内容进行初始化?

也许我只需要改变我的策略,让一个初始化函数在启动时完成所有的复制。除非还有别的办法?


当前回答

这是语言的局限。第6.7.8/4节:

具有静态存储持续时间的对象的初始化式中的所有表达式都应该是常量表达式或字符串字面量。

在第6.6节中,规范定义了必须考虑的常量表达式。不,它在哪里声明const变量必须被视为常量表达式。编译器对此进行扩展是合法的(6.6/10 -实现可以接受其他形式的常量表达式),但这会限制可移植性。

如果你可以改变my_foo,让它没有静态存储,你就可以了:

int main()
{
    foo_t my_foo = foo_init;
    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;
}

基本上有两种初始化:在编译时和在运行时。 静态存储变量的初始化属于编译时初始化。注意,static-storage变量包括:

没有static关键字的全局变量 带有static关键字的全局变量 带有static关键字的局部变量


但是这个规则背后的原理是什么呢? 在我看来,这很容易解释。 在编译完成之前,这些变量的值将被存储到可执行文件中。在那个时候没有代码可以运行!

这是语言的局限。第6.7.8/4节:

具有静态存储持续时间的对象的初始化式中的所有表达式都应该是常量表达式或字符串字面量。

在第6.6节中,规范定义了必须考虑的常量表达式。不,它在哪里声明const变量必须被视为常量表达式。编译器对此进行扩展是合法的(6.6/10 -实现可以接受其他形式的常量表达式),但这会限制可移植性。

如果你可以改变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;
}

我在代码中有这样的错误:

int A = 1;
int B = A;

解决办法是把它改成这样

int A = 1;
#define B A

编译器将内存中的一个位置赋给一个变量。第二个是尝试将第二个变量分配到与第一个变量相同的位置——这毫无意义。使用宏预处理器可以解决这个问题。