【问题标题】:Parameter checking in C preprocessorC预处理器中的参数检查
【发布时间】:2015-08-14 23:52:20
【问题描述】:

如何在编译时测试C中宏参数的字符串值?

我正在用 C (GNU) 为微控制器编写封装宏。

我有一些像这样工作的宏:

#define _ReadBits(port, mask)      (PORT ## port) & (mask)
#define ReadBits(portmask)         _ReadBits(portmask) 
#define SWITCH D, (1<<7)

我可以这样说:

foo = ReadBits(SWITCH);

我会得到的

foo = PORTD & (1<<7);

效果很好。我想扩展这些来做这样的事情:

#define _ConfigAnalog(port, mask)  BUILD_BUG_ON(port != B); AD1PCFGCLR = (mask)
#define ConfigAnalog(portmask)    _ConfigAnalog(portmask)

也就是说,如果参数port 不是B,我希望发生编译时错误(因为这个微控制器可以将端口B 配置为模拟)。

有没有办法在 C 中做到这一点?

【问题讨论】:

    标签: c macros c-preprocessor


    【解决方案1】:

    我自己想出来的:

    #define PORT_B_SUPPORTS_ANALOG
    
    #define __CheckPort(p)  PORT_##p##_SUPPORTS_ANALOG
    #define __ConfigAnalogBits(mask) AD1PCFGCLR = (mask)
    
    #define _ConfigAnalogBits(port, mask)  __CheckPort(port); __ConfigAnalogBits(mask)
    #define ConfigAnalogBits(portmask)     _ConfigAnalogBits(portmask)
    
    #define NO_GOOD C, (1<<3)
    #define VOLTAGE B, (1<<3)
    
    void tryit(void)
    {
        ConfigAnalogBits(VOLTAGE);
        //ConfigAnalogBits(NO_GOOD);
    }
    

    如果“端口”为 B,则 _CheckPort 编译为空语句。

    如果“端口”是其他任何内容,则会发生构建错误。

    【讨论】:

    • 避免使用以下划线开头后跟另一个下划线或大写字母的标识符(例如,避免使用__this_This),因为这些标识符是为实现保留的。
    • @dreamlax:谢谢;会修复的。
    • 测试宏参数的任何“字符串值”。它测试标识符名称。如果我的回答中的反对意见是你的,我认为重新考虑你的问题(我引用的)是否可能没有尽可能清楚地说明是公平的。
    • @Jens:第一行是否使用“字符串”而不是“标识符”——在我看来,这是一个可以理解的口语/错误——问题的其余部分非常清楚他的意思。
    【解决方案2】:

    如何在编译时测试 C 中宏参数的字符串值?

    你不能。

    根据C99 6.10.1 条件包含,预处理器条件必须是整数常量表达式,并且可以测试是否定义了宏(使用#if , #ifdef identifier#if defined(identifier))。

    【讨论】:

    • 我认为 C 预处理器是图灵完备的。所以你总是可以的;问题是如何。
    • @nerdfever.com 图灵完备性与任意输入数据操作无关。一种语言可以在月光下实现图灵完备。这并不意味着它可以对字符串做出决定。
    • @Gene:如果您可以在月光中编码字符串,那么我认为您可以对字符串做出决定。 (原则上无论如何;并不是说它实用。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多