Нет предупреждения при возврате NULL с gcc
С помощью gcc
5.2.0, я заметил, что этот код не генерирует предупреждение:
#include <stddef.h>
int function(void)
{
return NULL;
}
void procedure(void)
{
return NULL;
}
Я использовал флаги -Wall -Wextra -std=c99 -pedantic
и я использую archlinux Я не уверен, почему этот код работает на gcc
, особенно с тех пор, как clang
3.7.0 генерирует предупреждение.
Я также пытался с более старыми версиями gcc
как 4.9 или 4.7, и они оба генерируют предупреждения.
Предупреждения:
warning: return makes integer from pointer without a cast
а также
warning: ‘return’ with a value, in function returning void
Я должен упомянуть, что я попытался скомпилировать gcc 5.2 на Debian, и результат тот же. Таким образом, archlinux, похоже, не является проблемой.
Каково обоснование? Я не могу найти что-либо связанное с этим где-либо еще.
Спасибо!
3 ответа
Я заполнил отчет об ошибке здесь: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67730
Это было подтверждено и исправлено для 5.3, кажется!
Спасибо за вашу помощь.
Похоже, что это регрессия в gcc 5.2.0 - и, насколько я могу судить, странная.
С gcc 4.4.5 и 4.8.4 программа (после добавления необходимого #include <stddef.h>
) выдает предупреждения обоим return NULL;
операторы, даже без каких-либо дополнительных параметров командной строки.
С gcc 5.2.0 предупреждение не выводится даже при gcc -c -Wall -Wextra -std=c99 -pedantic
, Для второго, который возвращает значение из void
функция, диагностика обязательна.
Теперь вот странная часть.
$ gcc --version | head -n 1
gcc (GCC) 5.2.0
$ cat c.c
#include <stddef.h>
int function(void) {
#ifdef USE_NULL
return NULL;
#else
return ((void*)0);
#endif
}
void procedure(void) {
#ifdef USE_NULL
return NULL;
#else
return ((void*)0);
#endif
}
$ gcc -c c.c
c.c: In function ‘function’:
c.c:7:12: warning: return makes integer from pointer without a cast [-Wint-conversion]
return ((void*)0);
^
c.c: In function ‘procedure’:
c.c:15:12: warning: ‘return’ with a value, in function returning void
return ((void*)0);
^
$ gcc -c -DUSE_NULL c.c
$
когда USE_NULL
определяется, предупреждения не выдаются. Компилирование с gcc -E -DUSE_NULL
(который выводит вывод препроцессора в стандартный вывод) подтверждает, что NULL
определяется как ((void*)0)
, Но когда я заменяю NULL
с ((void*)0)
предупреждения выдаются (как и должно быть).
Я не знаю, что происходит. Однажды макрос NULL
был расширен, он должен быть неотличим от ((void*)0)
и все же поведение компилятора меняется в зависимости от того, какой из них используется.
Действительность первой функции зависит от того, как NULL
определено. Там нет проблем с первой функцией, если NULL
определяется как 0
, Но если это будет определено как (void *) 0
(что обычно имеет место в коде C) первая функция становится недействительной. GCC часто очень склонен к неявным преобразованиям указателя в целое число.
Вторая функция совершенно недействительна. В спецификации языка четко указано, что "оператор возврата с выражением не должен появляться в функции, тип возвращаемого значения void". Если он компилируется, это должен быть еще один пример того, как GCC чрезмерно допускает что-то.
Вам нужно запустить GCC в -pedantic
режим, если вы хотите, чтобы его диагностический вывод был связан со стандартным языком C. В режиме по умолчанию это не заслуживающий доверия компилятор C (по крайней мере, в терминах его диагностического вывода), и тот факт, что он "не выдает предупреждение", абсолютно ничего не значит.
Однако в моих экспериментах я не мог заставить GCC жаловаться на вторую функцию даже при -std=
а также -pedantic
переключатели. Похоже, ошибка в компиляторе.