我试图从通过变量上交的常量值初始化结构中的字段。
typedef struct _A{
uint a;
}A;
const A a = {9} ; const A b = { .a = 10 }; const A c = {0};
typedef struct _Z{
A a;
A b;
A c;
}Z;
Z z = { a,b,c };
但这会产生编译器错误:
initializer element is not constant
这不是很明显,因为a,b和c被声明为const,不应在运行时进行修改。
我想在内存中存储的内容如下:
0x00 9
0x04 10
0x08 0
因为struct只是一个整数数组。
现在的问题是,我如何才能告诉编译器(使用arm-none-eabi-gcc),变量
a
,b
和c
的使用与定义一样,并且可以/应该用其内容替换,因为唯一的对z
的引用将出现在正在运行的程序中?也许有些杂用,甚至是预处理器指令?
我在初始化
A
的同一宏中构造a
。看起来像这样,但是有点复杂。#define bar(name, ...)\
typedef struct __bar_##name{\
List(applydef, __VA_ARGS__)\
}bar_##name;\
const bar_##name name ={List(applyset, __VA_ARGS__)};
bar(foobar, a,b)
上面的代码由于过度使用define而被自我扩展。
我在这里接受的另一个解决方案是不生成新的结构,而是生成一个新的定义,我可以像这样将其放入宏中。
最佳答案
不幸的是,初始化程序{a,b,c}
不是常数,但是您对z
的声明要求它是常数。
[C99: 6.6/7]:
允许初始化程序中的常量表达式具有更大的自由度。该常数表达式应为以下值之一或计算为以下值之一:
算术常数表达式
空指针常量,
地址常数,或
一个对象类型的地址常量,加上或减去一个整数常量表达式。
[C99: 6.7.8/4]:
具有静态存储持续时间的对象的初始化程序中的所有表达式应为常量表达式或字符串文字。z
具有静态存储期限,因为您是在全局范围内声明的。如果将其声明移至函数中,则此规则将不适用。
尽管使用了a
,但名称b
,c
或const
都没有资格作为常量表达式:
[C99: 6.6/8]:
算术常数表达式应具有算术类型,并且仅应具有整数常量,浮点常量,枚举常量,字符常量和sizeof
表达式的操作数。算术常数表达式中的强制转换运算符只能将算术类型转换为算术类型,除非作为运算数的一部分转换为结果为整数常量的sizeof
运算符。
尽管struct _S
仅包装uint
,但这并不意味着它是uint
。的确,关于struct _Z
,您断言“该结构只是一个整数数组”是错误的:您没有考虑类型。
在这方面,C ++比C宽松得多,尤其是在constexpr
时代。
关于c - 从变量初始化结构中的字段,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30379937/