8

我正在开发一个 C 程序。有一个函数需要两个指针参数,调用它cmp()cmp()出于说明的原因,我在这里提供一个简化的替身:

int cmp(struct foo *a, struct foo *b)
{
    return a->bar == b->bar;
}

我想做一个 NULL 检查宏,如下所示:

#define SAFE_CMP(a,b) (((a) != NULL && (b) != NULL) ? cmp((a),(b)) : 0)

我认为这完全没问题。但是,在编译时同时使用-Wall了将警告视为错误的编译开关,下面的代码就很麻烦了:

int baz(struct foo *a)
{
   struct foo b;
   /* ... */
   return SAFE_CMP(a, &b); 
}

因为 gcc 警告“b 的地址永远不会是 NULL”

有没有办法解决这种情况?拥有各种辅助宏SAFE_CMP_1(safe_arg,unsafe_arg)SAFE_CMP_2(unsafe_arg,safe_arg)是我想要的最后一件事。我想要一个适用于所有情况的辅助宏。

4

4 回答 4

14

这似乎压制了我的警告:

#define SAFE_CMP(a,b) (((void *)(a) != NULL && (void *)(b) != NULL) ? cmp((a),(b)) : 0)

...但就个人而言,我只会将其创建safe_cmp()为函数本身。

int safe_cmp(struct foo *a, struct foo *b) {
    return (a && b) ? (a->bar == b->bar) : 0;
}
于 2010-07-01T03:05:37.507 回答
2

“我想要一个适用于所有情况的辅助宏。”

为什么?一种尺寸并不适合所有人。GCC 通过告诉您比较总会有一定的结果来帮您一个忙。堆栈变量的地址永远不会为 NULL。我会在 baz 中写出支票:

int baz(struct foo *a) {
   struct foo b;
   ...
   return a == NULL ? 0 : cmp(a, &b);
}

你也可以在cmp. 这取决于您如何定义前置条件和后置条件。

您的宏(不适用于 baz)的另一个可能问题是,a它将b被多次评估。提防:

SAFE_CMP(p++, p1++);
于 2010-07-01T03:05:53.503 回答
0

gcc选项-Wno-address似乎删除了警告。

于 2010-07-01T03:42:59.283 回答
-1

当您收到此类警告时,请考虑您的 if () 表达式中有双重 && && 错误的可能性

于 2019-10-19T08:40:27.287 回答