Reputation: 309
I'm using Keil uVision to compile this code for an embedded project.
void doSomething(void)
{
unsigned char a = 0x01;
unsigned char b = 0x02;
typedef struct
{
void *pVoid;
} test_t;
test_t t[] = {{&a}, {&b}};
}
On the last line I receive an error
error: #28: expression must have a constant value
I've read that this is an issue where the compiler does not know the size of the variable. I don't understand what that means.
The variables a and b are of a defined type, so their pointers will always be the same size? Regardless of their type, this is embedded so pointers are all the same size?
It works to make var a and b static, why? This being embedded, I don't want the memory allocated continuously so that is not a solution here.
UPDATE: I'm using Keil uVision 4.72.10.0 with Armcc v5.03.0.76 - I was able to get Keil to compile this, using the "--c99" flag, as found here.
Upvotes: 0
Views: 1430
Reputation: 180886
Your function is perfectly fine in modern C, or even in C99, but C90 had stricter rules for initializers, and your code does not comply with those.
Here is the relevant provision of C90:
All the expressions in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions.
(C90 6.5.7/4; emphasis added)
Structure types are aggregate types, so that applies to your code (when interperted according to C90). Where a
and b
identify function-scope variables, the expressions &a
and &b
are not constant expressions, so your code does not conform (to C90).
C99 drops the bit about aggregate or union type, and C2011 adds a provision for objects with thread storage duration (new in that version of C) to yield:
All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.
That does not apply to your code.
It seems, then, that your compiler is enforcing C90 rules. Perhaps there is an option to select a more recent standard, but if not, then your best alternative is probably to set the structure members' values with assignment statements instead of an initializer:
test_t t[2];
t[0].pVoid = &a;
t[1].pVoid = &b;
Upvotes: 6