2

I want to use code similar to the following (but a lot more complex - this is a simplified example) to initialize an array of structures, but during compilation I get the error "expression must have a constant value".

typedef struct
{
    int x;
    int y;
} windowStruct_t;

static const windowStruct_t windowStructInit =
{
    .x = 3,
    .y = 5,
};

// These get defined differently at times.  This is simplified for the example.
#define NUM_ARRAY_ELEMENTS (2)
#define REPEAT_NUM_ARRAY_ELEMENTS_TIMES(x) (x),(x)

// The following line causes the error "expression must have a constant value" twice.
windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = 
    { REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };

void someFunction( void )
{
    volatile int x = windowStruct[0].x;
}

void anotherFunction( void )
{
    volatile int y = windowStruct[1].y;
}

Manually expanding the macro and replacing the line that causes the error with the following gives the same result:

windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = 
    { windowStructInit, windowStructInit };

But this compiles without error:

windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
    { { .x = 3, .y = 5 }, { .x = 3, .y = 5 } };

If I move the array declaration inside of function scope, it compiles without errors (I am ignoring the fact that someFunction() and anotherFunction() now access different arrays and that their lifetimes are different):

void someFunction( void )
{
    windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = 
        { REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };

    volatile int x = windowStruct[0].x;
}

void anotherFunction( void )
{
    windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = 
        { REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };

    volatile int y = windowStruct[1].y;
}

Leaving the array declarations inside of function scope, if they are declared to be "static", the error message comes back:

void someFunction( void )
{
    static windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = 
        { REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };

    volatile int x = windowStruct[0].x;
}

So it seems that when the arrays are declared as automatic variables (on the stack) that they can be initialized in a way that isn't allowed when the memory allocation is static (whether inside function scope or in global scope where the allocation is static even without the "static" keyword). Is there a way to initialize the array in global scope using a const struct as in the original example?

I am using C, not C++. I don't want to use dynamic memory allocation. The compiler is TI's ARM compiler V16.6.0.STS as included in their Code Composer Studio environment.

10
  • Try to define windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = ... as static const windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] = ... and see what happens. Commented Aug 8, 2017 at 20:22
  • When it is in global scope, I get the same compilation error with "static", "const", "static const" or neither of them. Commented Aug 8, 2017 at 20:27
  • @MadPhysicist stop guessing, this is C, not some C++. Commented Aug 8, 2017 at 20:29
  • 1
    @SteveStrobel const structs are not compile-time constants. And "even without the static keyword" is because you're confusing the static storage class with static storage duration :) Commented Aug 8, 2017 at 20:30
  • 1
    repeating the initializer is correct, now write an answer about it and self-accept it. The other cannot be done, ever, at all. Commented Aug 8, 2017 at 20:31

1 Answer 1

3

A const object is not a C constant. Instead use constants which is required for non-automatic storage objects.

Define an initializer { .x = 3, .y = 5 }

typedef struct windowStruct_s {
  int x;
  int y;
} windowStruct_t;

#define windowStruct_t_default_initializer { .x = 3, .y = 5 }
#define NUM_ARRAY_ELEMENTS (2)
#define REPEAT_NUM_ARRAY_ELEMENTS_TIMES(x) x, x /* no () */

windowStruct_t windowStruct[NUM_ARRAY_ELEMENTS] = {
    REPEAT_NUM_ARRAY_ELEMENTS_TIMES(windowStruct_t_default_initializer) };

int someFunction(void) {
  volatile int x = windowStruct[0].x;
  return x;
}

int anotherFunction(void) {
  volatile int y = windowStruct[1].y;
  return y;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.