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

tomlogic picture tomlogic · Jun 11, 2010 · Viewed 264.4k times · Source

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;
} foo_t;

const foo_t foo_init = { 1, 2, 3 };
foo_t my_foo = foo_init;

int main()
{
    return 0;
}

Keep in mind this is a simplified version of a larger, multi-file project I'm working on. The goal was to have a single constant in the object file, that multiple files could use to initialize a state structure. Since it's an embedded target with limited resources and the struct isn't that small, I don't want multiple copies of the source. I'd prefer not to use:

#define foo_init { 1, 2, 3 }

I'm also trying to write portable code, so I need a solution that's valid C89 or C99.

Does this have to do with the ORGs in an object file? That initialized variables go into one ORG and are initialized by copying the contents of a second ORG?

Maybe I'll just need to change my tactic, and have an initializing function do all of the copies at startup. Unless there are other ideas out there?

Answer

AnT picture AnT · Jun 11, 2010

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.