C宏-避免宏扩展

古拉·普拉萨德(Guru Prasad)

我有以下宏

#define REG_PWR_CTRL 0x2D  
#define REG_FIFO_CTL 0x38

#define VERBOSE(...) \
    if(verbose) \
            printf(__VA_ARGS__);

#define READ_REGISTER(i2c_dev_file, REGISTER, variable) \
{ \
    variable = i2c_smbus_read_byte_data(i2c_dev_file, REGISTER); \
}

#define WRITE_REGISTER_VERBOSE(i2c_dev_file, REGISTER, value) \
{ \
    short int var = 0; \
    i2c_smbus_write_byte_data(i2c_dev_file, REGISTER, value); \
    usleep(100); \
    READ_REGISTER(i2c_dev_file, REGISTER, var); \
    VERBOSE(#REGISTER "    :0x%02X\n", var); \
}

我希望REGISTER在下一行中不要扩展字段
VERBOSE(#REGISTER " :0x%02X\n", var); \

例如,当我写
WRITE_REGISTER_VERBOSE(i2c_dev_fd, REG_PWR_CTRL, 0x1A);
WRITE_REGISTER_VERBOSE(i2c_dev_fd, REG_FIFO_CTL, 0xC6);
我得到的输出
0x2D :0x1A
0x38 :0xC6
,我想获得
REG_PWR_CTRL :0x1A
REG_FIFO_CTL :0xC6

我遇到了很多关于添加额外级别的间接访问的帖子。
我尝试了此处描述的答案https://stackoverflow.com/a/2653351/1761555 ..尽管我相信该答案完全是针对另一个问题的。

我所做的是

#define STRINGIFY(label) (#label)

#define WRITE_REGISTER_VERBOSE(i2c_dev_file, REGISTER, value) \
{ \
    short int var = 0; \
    i2c_smbus_write_byte_data(i2c_dev_file, REGISTER, value); \
    usleep(100); \
    READ_REGISTER(i2c_dev_file, REGISTER, var); \
    VERBOSE("%s    :0x%02X\n", STRINGIFY(REGISTER), var); \
}

但这仍然给我与以前相同的输出

有什么办法可以做到这一点?

巴西尔·斯塔林凯维奇

你可以做REG_PWR_CTRLREG_FIFO_CTL一些枚举值,如

  enum registers_en {
     REG__NONE,
     REG_PWR_CTRL = 0x2d,
     REG_FIFO_CTL = 0x38,
  };

然后REG_PWR_CTRL成为某个枚举值的真实标识符,并且不会在其他内容中进行宏扩展(因为enum定义不是宏定义,并且不会由cpp预处理器处理)。

因此,定义一个这样的枚举,并预处理您的源代码(例如,使用gcc -C -E yoursource.c > yoursource.i),然后less yoursource.i在预处理文件中查找(例如,使用)。所有的出现REG_PWR_CTRL仍会存在。

请注意,从概念上讲,预处理器是编译器的第一阶段:即使在当前GCC 4.8之类的编译器中,预处理器不是外部程序,而是通过libcpp内部库实现的,编译器的工作方式是先对源代码进行预处理并获取流的词位,然后出现的REG_PWR_CTRL逗留词位(而不是字面常量0x2d,当您#define REG_PWR_CTRL 0x2d......)。

您需要阅读有关预处理器cpp的更多信息,并养成研究预处理形式的习惯。

enum-s的另一个优点是,如果您使用调试信息(例如gcc -g)进行编译,则调试器就会gdb知道enum

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章