代码之家  ›  专栏  ›  技术社区  ›  tomlogic

尝试用常量初始化变量时出现错误“initializer element is not constant”

  •  167
  • tomlogic  · 技术社区  · 14 年前

    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解决方案。

    也许我只需要改变我的策略,让一个初始化函数在启动时完成所有的拷贝。除非有其他想法?

    4 回复  |  直到 9 年前
        1
  •  293
  •   Community Egal    4 年前

    在C语言中,具有静态存储持续时间的对象必须用 常量表达式 ,或使用包含常量表达式的聚合初始值设定项。

    “大”对象在C中永远不是常量表达式,即使该对象被声明为 const .

    此外,在C语言中,“常量”一词是指 文字常量 (就像 1 , 'a' 0xFF 依此类推),枚举成员,以及诸如 sizeof . Const限定对象(任何类型)是 不是常量

    例如,这是 常数

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

    N 将是C++中的常量,但在C.中不是常数。所以,如果你试着

    static int j = N; /* ERROR */
    

    您将得到相同的错误:尝试用非常量初始化静态对象。

    #define 声明命名常量,也诉诸于 #定义 创建命名聚合初始值设定项。

        2
  •  78
  •   R Samuel Klatchko    14 年前

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

    具有静态存储持续时间的对象的初始值设定项中的所有表达式应为常量表达式或字符串文字。

    在第6.6节中,规范定义了必须视为常量表达式的内容。不,它在哪里声明常量变量必须被视为常量表达式。编译器对此进行扩展是合法的( 6.6/10 - An implementation may accept other forms of constant expressions )但这会限制可移植性。

    如果你能改变 my_foo 所以它没有静态存储,您可以:

    int main()
    {
        foo_t my_foo = foo_init;
        return 0;
    }
    
        3
  •  5
  •   TheMadHau5 achoora    5 年前

    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;
    }
    
        4
  •  2
  •   valenumr    8 年前

    #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;
    }
    
        5
  •  2
  •   Zaman    3 年前

    2021年:谁因为 arm-none-eabi-gcc.exe
    将工具链更改为 gnu-tools-for-stm32.9-2020-q2-update .

    在gccv8.1+中,支持嵌套常量初始值设定项,下面的代码将被编译。

    const int a = 1;
    const int b = a +1;
    
    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;
    }
    

    arm-none-eabi-gcc.exe 在里面 gnu-tools-for-stm32.7-2018-q2-update 基于 gcc v7.3.1 上面的代码不会编译!但是 gnu-tools-for-stm32.9-2020-q2-更新 使用 gcc v9.3.1 并将编译。

    有关更多信息,请参见以下内容:
    Why "initializer element is not a constant" is... not working anymore?

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960#c18

        6
  •  0
  •   xjtuecho    4 年前

    gcc 7.4.0不能编译如下代码:

    #include <stdio.h>
    const char * const str1 = "str1";
    const char * str2 = str1;
    int main() {
        printf("%s - %s\n", str1, str2);
        return 0;
    }
    

    常量字符*str2=str1;

    函数名当然是一个编译时常量。所以这段代码可以工作:

    void func(void)
    {
        printf("func\n");
    }
    typedef void (*func_type)(void);
    func_type f = func;
    int main() {
        f();
        return 0;
    }
    
        7
  •  -2
  •   Bruce Barnett    3 年前

    int A = 1;
    int B = A;
    

    解决办法是把它改成这样

    int A = 1;
    #define B A
    

    编译器将内存中的一个位置分配给一个变量。第二种方法是尝试将第二个变量赋给与第一个变量相同的位置,这是没有意义的。使用宏预处理器解决了这个问题。