gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 16:49:34 32 4
gpt4 key购买 nike

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

让我们用一个简单的例子:

#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 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_; })

关于检查函数调用不作为参数传递(C 宏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20307744/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com