使用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
我应该提一下,我尝试在Debian上编译gcc 5.2,结果是一样的。所以archlinux似乎不是问题所在。
理由是什么?我似乎无法在其他任何地方找到与此相关的任何内容。
谢谢!
答案 0 :(得分: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
进行编译(将预处理器的输出打印到stdout)确认NULL
被定义为((void*)0)
。但是当我用NULL
替换((void*)0)
时,会产生警告(应该是这样)。
我不知道发生了什么。宏NULL
扩展后,它应该与((void*)0)
无法区分,但编译器的行为会根据使用的内容而发生变化。
答案 1 :(得分:1)
第一个函数的有效性取决于NULL
的定义方式。如果将NULL
定义为0
,则第一个函数没有问题。但如果碰巧定义为(void *) 0
(通常是C代码中的情况),则第一个函数变为无效。 GCC通常对隐式指针到整数转换非常宽容。
第二个功能是无效的。语言规范明确指出“带有表达式的return语句不应出现在返回类型为void的函数中”。如果它编译,它必然是GCC过于宽容的另一个例子。
如果您希望其诊断输出与标准C语言相关,则需要在-pedantic
模式下运行GCC。在默认模式下,它不是一个可信的C编译器(至少在其诊断输出中),并且它“不发出警告”这一事实绝对没有任何意义。
然而在我的实验中,即使使用-std=
和-pedantic
开关,我也无法让GCC抱怨第二个功能。它看起来像编译器中的一个错误。
答案 2 :(得分:1)