views:

465

answers:

1

I am getting an error message "expression must have constant value" when initializing an array of structures with an external constant integer.

File1.c:

const unsigned char data1[] =
{
    0x65, 0xF0, 0xA8, 0x5F, 0x5F,
    0x5F, 0x5F, 0x31, 0x32, 0x2E,
    0x31, 0xF1, 0x63, 0x4D, 0x43, 
    0x52, 0x45, 0x41, 0x54, 0x45,
    0x44, 0x20, 0x42, 0x59, 0x3A,
    0x20, 0x69, 0x73, 0x70, 0x56, 
// ...
};
const unsigned int data1_size = sizeof(data1);

File2.c:

const unsigned char data2[] =
{
    0x20, 0x44, 0x61, 0x74, 0x61,
    0x20, 0x52, 0x6F, 0x77, 0x20,
    0x3D, 0x20, 0x34, 0x38, 0x12, 
//...
};
const unsigned int data2_size = sizeof(data2);

Get_Byte.c:

extern const unsigned char * data1;
extern const unsigned int    data1_size;
extern const unsigned char * data2;
extern const unsigned int    data2_size;

struct Array_Attributes
{
    const unsigned char *    p_data;
    const unsigned int       size;
};

const struct Array_Attributes Data_Arrays[] =
{
    {data1, data1_size},  // Error message is for data1_size here.
    {data2, data2_size},  // Another error message generated for data2_size here.
};

I have also removed the const qualifier from the size field of Array_Attributes and get the same error message.

Why is the compiler complaining about a constant value expression when data1_size and data2_size are const unsigned int but in a different translation unit?

I want a constant array of [array address, array size] which is generated at compile time.

I am using Green Hills ccarm 4.24, on Windows XP, C language NOT C++.

+4  A: 

C's const qualifier has little to do with what the compiler considers a constant expression, in this case. In an initializer, ie

const struct attributes attrs[] = {
    { expr1, expr2 }, 
    ...
}

expr1 and expr2 must have very specific forms to be acceptable to the compiler. The upshot of these restrictions is that the expressions can be evaluated without fetching from program variables, since these aren't in existence at compilation.

You're attempting to use data1_size and data2_size, which are not compile time constants by these rules.

By the way, the declarations

const unsigned char data1[] = { ... };

and

extern const unsigned char *data1;

are not compatible and will lead to a bug in your code. The latter should be

extern const unsigned char data1[];
Dale Hagglund
My understanding is that `data1[]` and `*data1` are the same. How are they different and why will they lead to bugs?
Thomas Matthews
The only place they can be substituted is with in a parameter declaration. `extern char *foo` tells the compiler that `foo` is a 4-byte variable containing a pointer to a character. `extern char bar[]` tells the compiler that `bar` is an address constant that points to a block of characters of unknown size.`foo[i]` first fetches the 4-byte pointer, adds `i`, and then dereferences that to get a character. `bar[i]` takes the value `bar`, adds `i`, and dereferences.
Dale Hagglund
http://c-faq.com/aryptr/aryptr1.html
Alok