使用 gcc 返回 NULL 时没有警告

No warning when returning NULL with 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

我应该提一下,我尝试在 Debian 上编译 gcc 5.2,结果是一样的。所以archlinux好像不是问题。

理由是什么?我似乎无法在其他任何地方找到与此相关的任何内容。

谢谢!

第一个函数的有效性取决于 NULL 的定义方式。如果 NULL 定义为 0,那么第一个函数没有问题。但是,如果它恰好被定义为 (void *) 0(在 C 代码中通常是这种情况),则第一个函数将无效。 GCC 通常对隐式指针到整数的转换非常宽容。

第二个函数完全无效。语言规范明确指出 "A return statement with an expression shall not appear in a function whose return type is void." 如果它编译,那一定是 GCC 对某些事情过于宽容的另一个例子。

如果您希望其诊断输出与标准 C 语言相关,则需要 运行 GCC -pedantic 模式。在默认模式下,它不是一个可靠的 C 编译器(至少在它的诊断输出中),而且它 "does not issue a warning" 的事实绝对没有任何意义。

然而,在我的实验中,即使使用 -std=-pedantic 开关,我也无法让 GCC 抱怨第二个函数。看起来像是编译器中的错误。

这似乎是 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 也不会产生警告。对于第二个 returns 来自 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)。但是当我用 ((void*)0) 替换 NULL 时,会产生警告(因为它们应该是)。

我不知道发生了什么。一旦宏 NULL 被扩展,它应该与 ((void*)0) 没有区别,但编译器的行为会根据使用的宏而改变。

我在这里填写了错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67730

已确认,似乎已修复 5.3!

感谢您的帮助。