tags:

views:

106

answers:

2

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?

+6  A: 

It has to do with C language. In C language objects with static storage duration has 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). 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 C = 5; /* not a constant in C */

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

static int j = C; /* ERROR */

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

AndreyT
+3  A: 

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;
}
R Samuel Klatchko