在我工作的项目中,我们有一些实用程序宏,它们多次引用它们的参数。
让我们使用一个简单的例子:
#define ABS(a) ( (a) < 0 ? (-(a)) : (a) )
现在这是一个很大的代码库,当我们查看代码时,我偶尔会发现一个函数调用被传递给宏。 这不是错误,但这意味着多次进行函数调用,这是我通常不想要的。
在这种情况下,我们至少可以用fabsf
,fabs
,abs
取代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) ))
注意:我发现这已经非常方便地指出了一些不好的宏用法,但由于它有误报,所以它不能留下来。
使用_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 */ \
)
这还不是一个可行的解决方案 - 我们仍然支持不支持泛型的编译器。
答案 0 :(得分:5)
我确实在MirOS C Preprocessor manual in the section on duplicating side effects中找到了这个技巧:
#define min(X, Y) \
({ typeof (X) x_ = (X); \
typeof (Y) y_ = (Y); \
(x_ < y_) ? x_ : y_; })