keil错误#28表达式必须具有常量值

Mic*_*ael 0 c

我正在使用Keil uVision为嵌入式项目编译此代码.

void doSomething(void)
{
    unsigned char a = 0x01;
    unsigned char b = 0x02;

    typedef struct
    {
        void *pVoid;
    } test_t;

    test_t t[] = {{&a}, {&b}};
}
Run Code Online (Sandbox Code Playgroud)

在最后一行,我收到一个错误

错误:#28:表达式必须具有常量值

我读过这是编译器不知道变量大小的问题.我不明白这意味着什么.

变量a和b是定义的类型,因此它们的指针总是相同的大小?无论它们的类型如何,这是嵌入式的,所以指针大小都相同?

它可以使var a和b静态,为什么?这是嵌入式的,我不希望连续分配内存,因此这不是解决方案.

更新:我正在使用Keil uVision 4.72.10.0和Armcc v5.03.0.76 - 我能够使用"--c99"标志让Keil编译它,如此处所示.

Joh*_*ger 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;
Run Code Online (Sandbox Code Playgroud)