首页 > 解决方案 > 设计时的 C 宏参数测试

问题描述

我需要在设计时(预处理器)进行宏变量检查,更具体地说,该数字适合 24 位。该宏旨在用于 if() 语句,所以我不知道如何测试它。

这是一个 ARM systick 计时器(24 位),很多时候我都忘记了#define 正确的值,尤其是在更改 MCU 时钟时,当然,我的 if() 从未触发,这个愚蠢的错误很难调试。

所以在这个例子中,有一个技巧可以在 PARAMETER > 24 bits 时强制 gcc 出错?

    #define PARAMETER   20000000  // over 24 bits, should throw a error at design time
    #define MyMacro(var, par)       (var > par)

    uint32_t variable;

    if(MyMacro(variable,PARAMETER))
    {
        // do something
        //  do something WRONG because PARAMETER > 24 bits


        // Actually this is working as expected, test for < is valid because 
// _Static_assert() is check for TRUE condition
// But I am still trying to find a way to combine this in original macro
        _Static_assert(PARAMETER < 0xFFFFFF, "Ooopss... ERROR");

    }

提前致谢!

标签: cmacros

解决方案


不幸的是,_Static_assert在语法上定义为声明,这意味着您不能直接在表达式中使用它。

然而,_Static_assert无论如何都不需要,因为你可以完美地(没有漂亮的编译时错误报告——但你是一名程序员,你应该能够找出编译时失败一个稍微技术性的编译时错误消息)模仿它

#define static_assert_0expr(Truth) ((int)(0*sizeof(struct { int _ : (Truth)?1:-1; })))

(或等价物)并且您可以放入表达式(甚至是整数常量表达式)没问题:

#define static_assert_0expr(Truth) ((int)(0*sizeof(struct { int _ : (Truth)?1:-1; })))

#define PARAMETER   20000000  // over 24 bits, should throw a error at design time
#define MyMacro(var, par)       (static_assert_0expr((par)<0xffffff) + ((var) > (par)))

//or this, but this is won't preserve integer-constant expressions because of the comma:
/*#define MyMacro(var, par)       (static_assert_0expr((par)<0xffffff), ((var) > (par)))*/
//alternatively: (static_assert_0expr(assertion) ? (expr) : (expr)) is the most
//general form (though it leads to larger preprocessor expansions, which may worsen debugging experience with cc -E)

#include <stdint.h>
int main()
{
    static_assert_0expr(1)+1;
    uint32_t variable;

    if(MyMacro(variable,PARAMETER))
    {
    }
}

上面的static_assert_0expr宏也可以用_Static_assert

#define static_assert_0expr(Truth) \
   ((int)(0*sizeof(struct { int _; _Static_assert(Truth,""); })))

或者您可以将其正文直接粘贴到其中MyMacro并自定义消息(但我认为_Static_assert其自定义编译时错误消息具有对 C 的不必要添加,因此不希望使用它)。


推荐阅读