“初始化元素不是常数” - 但显然是

时间:2014-12-23 23:19:51

标签: c macros avr avr-gcc

我知道这个消息意味着什么,但不知道为什么会这样。

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))) })
};

对我来说看起来很稳定。

问题出在哪里?

2 个答案:

答案 0 :(得分:3)

从C11 6.7.9 / 4(C99有相似的文字):

  

具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式   应该是常量表达式或字符串文字。

从C11 6.6“常量表达式”:

  

初始值设定项中的常量表达式允许更多纬度。这样的常数   表达式应为或评估为以下之一:

     
      
  • 算术常量表达式
  •   
  • 一个空指针常量,
  •   
  • 地址常量,或
  •   
  • 完整对象类型的地址常量加上或减去整数常量   表达
  •   

复合文字不是那些项目符号,因此初始化程序中不允许使用它。

如果复合文字的初始值设定项都是符合这些条件的常量表达式,那么为什么是不允许的,我没有看到任何理由。

但是,您只需使用不带复合文字的初始值设定项即可解决此问题:

const xrgb_t COLORS[] = {
    { .r = ........... , .g = ............., .b = ........ },
    { .r = .......  // etc.
};

通过将宏重命名为仅提供{ }部分,然后使用另一个原始名称为(const xrgb_t) rgb24_xrgb(X)的宏来制作复合文字,您可以在现有代码中轻松完成此操作或者其他什么。

NB。使复合文字const允许编译器将其存储在只读区域中。

答案 1 :(得分:-1)

以下作品 干净利落地编译 它仍然需要很多:

// Color structure
struct xrgb_t
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
};


#define xrgb(rr, gg, bb) ((struct xrgb_t) { .r = ((unsigned char)(rr)), .g = ((unsigned char)(gg)), .b = ((unsigned char)(bb)) })
#define rgb24_r(c) ((((unsigned char) (c)) >> 16) & 0xFF)
#define rgb24_g(c) ((((unsigned char) (c)) >> 8) & 0xFF)
#define rgb24_b(c) ((((unsigned char) (c)) >> 0) & 0xFF)
#define rgb24_xrgb(c) xrgb(rgb24_r(c), rgb24_g(c), rgb24_b(c))


// Table of colors
const struct xrgb_t COLORS[] =
{
    rgb24_xrgb(0xB14835), // brick red
    rgb24_xrgb(0x4C1661), // indigo
    rgb24_xrgb(0xA3268E), // royal purple
};

我首选的方法是:

struct xrgb_t
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
};

#define set_xrgb(y)  {((y)>>16)&0xFF}, {((y)>>8)&0xFF}, {((y)&0xFF)}
// Table of colors
const struct xrgb_t COLORS[] =
{
    set_xrgb(0xB14835), // brick red
    set_xrgb(0x4C1661), // indigo
    set_xrgb(0xA3268E)  // royal purple
};