繁体   English   中英

检查函数调用不作为参数传递(C宏)

[英]Checking function calls are not passed as arguments (C macros)

在一个我从事的项目中,我们有一些实用程序宏,它们多次引用它们的参数。

让我们使用一个简单的示例:

#define ABS(a)  ( (a) < 0 ? (-(a)) : (a) )

现在这是一个庞大的代码库,在我们回顾代码的同时,我时不时地发现一个函数调用被传递给宏。 这不是一个错误 ,但是它意味着函数调用被多次执行,而我通常不希望这样做。

在这种情况下,我们至少可以用fabsffabsabs代替float / double / int ,但是让我们假设并非总是有好的内置替代方法,并且宏将保留为宏。

例:

f = ABS(dot_v3v3(vel, sp));

/* expands into */
f = ( ( dot_v3v3(vel, sp) ) < 0 ? (-( dot_v3v3(vel, sp) )) : ( dot_v3v3(vel, sp) ) );

所以我的问题是:

可以检测到宏内使用的函数调用(警告或错误)吗?


部分解决方案:

这是我已经检查过的一些内容...

比较指针

这将导致函数调用无法编译,但有一个缺点,如“ 1”之类的常量也会给出错误以及诸如(b-c)之类的表达式。

#define ABS(a)  ((void)((&a) == (&a)), ( (a) < 0 ? (-(a)) : (a) ))

注意:我发现指出某些错误的宏用法已经很方便了,但是由于它具有假阳性,因此不能保留。

C11泛型

使用_Generic ,您可以将C宏转换为内联函数的包装。 这意味着在宏中多次调用函数的问题就消失了。

#define ABS(a) \
    _Generic((a), \
        long double: my_abs_double(a), \
        float: my_abs_float(a), \
        int:  my_abs_int(a) \
        /* ... and so on, char, long, short... etc */ \
        )

这不是一个可行的解决方案-我们仍然支持不支持泛型的编译器。

我确实在MirOS C预处理程序手册的重复副作用部分找到了这个技巧:

 #define min(X, Y)                \
 ({ typeof (X) x_ = (X);          \
    typeof (Y) y_ = (Y);          \
    (x_ < y_) ? x_ : y_; })

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM