我使用Keil uVision为嵌入式项目编译此代码。
void doSomething(void)
{
unsigned char a = 0x01;
unsigned char b = 0x02;
typedef struct
{
void *pVoid;
} test_t;
test_t t[] = {{&a}, {&b}};
}
在最后一行,我收到错误
错误:#28:表达式必须具有常量值
我已经读过这是编译器不知道变量大小的问题。我不明白这意味着什么。
变量a和b是定义类型,因此它们的指针总是相同的大小?无论它们的类型如何,这都是嵌入式的,因此指针的大小都相同?
它可以使var a和b静态,为什么?这是嵌入式的,我不希望连续分配内存,因此这不是解决方案。
更新: 我使用Keil uVision 4.72.10.0和Armcc v5.03.0.76 - 我能够让Keil编译它,使用" - c99" flag,已找到here。
答案 0 :(得分:6)
您的功能在现代C中甚至在C99中都非常好,但C90对初始化程序有更严格的规则,而且您的代码不符合这些规则。
以下是C90的相关规定:
具有静态的对象的初始值设定项中的所有表达式 存储持续时间 或在具有的对象的初始化列表中 聚合或联合类型 应为常量表达式。
(C90 6.5.7 / 4;重点补充)
结构类型是聚合类型,因此适用于您的代码(根据C90进行交互时)。 a
和b
标识函数范围变量的情况,表达式&a
和&b
不是常量表达式,因此您的代码不符合(C90)。
C99删除了关于聚合或联合类型的位,C2011为具有线程存储持续时间的对象(在该版本的C中新增)添加了一个条款,以产生:
初始化程序中具有静态或。的对象的所有表达式 线程存储持续时间应为常量表达式或字符串 文字。
不适用于您的代码。
然后,您的编译器似乎正在执行C90规则。也许有一个选项可以选择更新的标准,但如果没有,那么你最好的选择可能是用赋值语句而不是初始值设置结构成员的值:
test_t t[2];
t[0].pVoid = &a;
t[1].pVoid = &b;