我知道消息的含义,但不知道为什么会发生。
main.c:26:2: error: initializer element is not constant
rgb24_xrgb(0xB14835), // brick red
我的代码:
typedef uint32_t rgb24_t;
// Color structure
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} xrgb_t;
// Table of colors
const xrgb_t COLORS[] = {
rgb24_xrgb(0xB14835), // brick red
rgb24_xrgb(0x4C1661), // indigo
rgb24_xrgb(0xA3268E), // royal purple
};
这是我的宏:
#define xrgb(rr, gg, bb) ((xrgb_t) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) })
#define rgb24_r(c) ((((rgb24_t) (c)) >> 16) & 0xFF)
#define rgb24_g(c) ((((rgb24_t) (c)) >> 8) & 0xFF)
#define rgb24_b(c) ((((rgb24_t) (c)) >> 0) & 0xFF)
#define rgb24_xrgb(c) xrgb(rgb24_r(c), rgb24_g(c), rgb24_b(c))
预处理器输出在这里:
const xrgb_t COLORS[] = {
((xrgb_t) { .r = ((uint8_t)(((((rgb24_t) (0xB14835)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xB14835)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xB14835)) >> 0) & 0xFF))) }),
((xrgb_t) { .r = ((uint8_t)(((((rgb24_t) (0x4C1661)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0x4C1661)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0x4C1661)) >> 0) & 0xFF))) }),
((xrgb_t) { .r = ((uint8_t)(((((rgb24_t) (0xA3268E)) >> 16) & 0xFF))), .g = ((uint8_t)(((((rgb24_t) (0xA3268E)) >> 8) & 0xFF))), .b = ((uint8_t)(((((rgb24_t) (0xA3268E)) >> 0) & 0xFF))) })
};
对我来说看起来很稳定。
问题出在哪儿?
从C11 6.7.9 / 4(C99具有类似文本):
具有静态或线程存储持续时间的对象的初始化程序中的所有表达式应为常量表达式或字符串文字。
从C11 6.6“常量表达式”开始:
初始值设定项中的常量表达式允许更大的自由度。该常数表达式应为以下值之一或计算为以下值之一:
- 算术常数表达式
- 空指针常量,
- 地址常数,或
- 完整对象类型加上或减去整数常量表达式的地址常量。
复合文字不是这些要点,因此在初始化程序中是不允许的。
如果复合文字的初始化程序都是满足这些条件的常量表达式,我看不出为什么不允许这样做的任何理由。
但是,您可以通过不使用复合文字的初始化程序来解决此问题:
const xrgb_t COLORS[] = {
{ .r = ........... , .g = ............., .b = ........ },
{ .r = ....... // etc.
};
在现有代码中,通过重命名宏以给出{ }
部分,然后再使用另一个具有原始名称的宏(const xrgb_t) rgb24_xrgb(X)
来完成复合文字或其他操作,这应该很容易做到。
注意 const
编写复合文字可以使编译器将其存储在只读区域中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句