Как обойти предупреждение GCC, «адрес XXX никогда не будет NULL»? - PullRequest
5 голосов
/ 01 июля 2010

Я работаю над программой на Си. Есть функция, которая принимает два аргумента-указателя, называем ее 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) и т. Д., Последнее, что я хочу. Я хотел бы иметь один вспомогательный макрос, применимый ко всем ситуациям.

Ответы [ 3 ]

11 голосов
/ 01 июля 2010

Это, кажется, подавляет для меня предупреждение:

#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;
}
2 голосов
/ 01 июля 2010

«Мне бы хотелось, чтобы один вспомогательный макрос подходил для любой ситуации.»

Почему?Один размер не подходит для всех.GCC оказывает вам услугу, сообщая вам, что сравнение всегда будет иметь определенный результат.Адрес переменной стека никогда не будет равен NULL.Я просто выписал бы чек в базе:

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

Вы также можете сделать это в cmp.Это зависит от того, как вы определяете предварительные и постусловия.

Другая возможная проблема с вашим макросом (не применимо для baz) заключается в том, что a и b будут оцениваться несколько раз.Остерегайтесь:

SAFE_CMP(p++, p1++);
0 голосов
/ 01 июля 2010

Опция gcc -Wno-address, похоже, удаляет предупреждения.

...