Error “initializer element is not constant” when trying to initialize variable with const

前端 未结 5 1714
清酒与你
清酒与你 2020-11-21 13:02

I get an error on line 6 (initialize my_foo to foo_init) of the following program and I\'m not sure I understand why.

typedef struct foo_t {
    int a, b, c;         


        
相关标签:
5条回答
  • 2020-11-21 13:44

    This is a bit old, but I ran into a similar issue. You can do this if you use a pointer:

    #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;
    }
    
    0 讨论(0)
  • 2020-11-21 13:52

    gcc 7.4.0 can not compile codes as below:

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

    constchar.c:3:21: error: initializer element is not constant const char * str2 = str1;

    In fact, a "const char *" string is not a compile-time constant, so it can't be an initializer. But a "const char * const" string is a compile-time constant, it should be able to be an initializer. I think this is a small drawback of CLang.

    A function name is of course a compile-time constant.So this code works:

    void func(void)
    {
        printf("func\n");
    }
    typedef void (*func_type)(void);
    func_type f = func;
    int main() {
        f();
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-21 13:56

    In C language, objects with static storage duration have to be initialized with constant expressions, or with aggregate initializers containing constant expressions.

    A "large" object is never a constant expression in C, even if the object is declared as const.

    Moreover, in C language, the term "constant" refers to literal constants (like 1, 'a', 0xFF and so on), enum members, and results of such operators as sizeof. Const-qualified objects (of any type) are not constants in C language terminology. They cannot be used in initializers of objects with static storage duration, regardless of their type.

    For example, this is NOT a constant

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

    The above N would be a constant in C++, but it is not a constant in C. So, if you try doing

    static int j = N; /* ERROR */
    

    you will get the same error: an attempt to initialize a static object with a non-constant.

    This is the reason why, in C language, we predominantly use #define to declare named constants, and also resort to #define to create named aggregate initializers.

    0 讨论(0)
  • 2020-11-21 13:56

    Just for illustration by compare and contrast The code is from http://www.geeksforgeeks.org/g-fact-80/ /The code fails in gcc and passes in 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;
    }
    
    0 讨论(0)
  • 2020-11-21 13:58

    It's a limitation of the language. In section 6.7.8/4:

    All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

    In section 6.6, the spec defines what must considered a constant expression. No where does it state that a const variable must be considered a constant expression. It is legal for a compiler to extend this (6.6/10 - An implementation may accept other forms of constant expressions) but that would limit portability.

    If you can change my_foo so it does not have static storage, you would be okay:

    int main()
    {
        foo_t my_foo = foo_init;
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题