Как избежать "null аргумент, где требуется ненулевой" предупреждение компилятора
Компиляция следующего кода:
#include <string.h>
#define FOO (NULL)
int main(int argc, char *argv[])
{
char *foo;
if (FOO)
foo = strdup(FOO);
return 0;
}
Приводит к следующему предупреждению компилятора:
foo.c: In function ‘main’:
foo.c:9:3: warning: null argument where non-null required (argument 1) [-Wnonnull]
foo = strdup(FOO);
^
Однако strdup
не будет вызываться, если FOO
является NULL
из-за проверки if (FOO)
. Есть ли способ избежать этого предупреждения?
Спасибо!
2 ответа:
Если идея состоит в том, чтобы присвоить значение
foo
, еслиFOO
определено, вы можете попробовать://#define FOO "lorem ipsum" int main() { char *foo; #ifdef FOO foo = strdup(FOO); #endif }
У него также есть преимущество, что весь код
if
не включается, когда он не нужен.
Вы правы, что вы защитили вызов
Но та часть компилятора, которая выдает предупреждение для вызова функции, не является той же самой частью, которая знает, что вызов никогда не может произойти.strdup
с предложением, чтобы гарантировать, чтоstrdup
никогда не вызывается с аргументомNULL
.Вместо этого вы можете скрыть
NULL
выражением, которое гарантирует, что сгенерированное выражение аргумента никогда не может бытьNULL
.Например
if (FOO) foo = strdup(FOO?FOO:"");
Или
if (FOO) foo = strdup(FOO + !FOO);
Здесь "ясно" (по крайней мере компилятору), что
strdup
не может быть вызвано со значениемNULL
, и Ваше предложениеif
гарантирует, что оно никогда не вызывается с тем, что было, больше не является значениемNULL
.В этот момент мы машем руками и говорим, что компилятор оптимизирует все это, и чтобы помочь нам визуально оптимизировать все это, у нас есть:
#define NON_NULL(x) ((x)?(x):"")
И для отладочных сборок, что-то вроде:
#define NON_NULL(x) ((x)?(x):(abort(),""))
Мы might использует расширение GNU
?:
(с необязательным пропуском среднего предложения по умолчанию к первому предложению), чтобы избежать оценки(x)
более одного раза.#define NON_NULL(x) ((x)?:"")
И для отладочных сборок, что-то вроде:
Теперь вы можете представить нечто технически более неясное, но, по-видимому, более значимое:#define NON_NULL(x) ((x)?:(abort(),"")
if (FOO) foo = strdup(NON_NULL(FOO));
И притворимся, что
NON_NULL
- Это какая-то формальная нотация и подтверждение.