为什么 gcc 和 clang 不对写入地址 0 发出警告?

ein*_*ica 5 c gcc pointers clang compiler-warnings

错误代码如下:

#include <stdio.h>
#include <string.h>

void isEven (int *isFlag, int num) {
    if (num % 2 == 0) {
        *isFlag = 1;
    } else {
        *isFlag = 0;
    }
}

int main() {
    int num = 4;
    int *isFlag = 0;
    isEven(isFlag, num);
    printf("%d", isFlag);
}  
Run Code Online (Sandbox Code Playgroud)

最近在这里发布了一个问题。问题本身并不重要,(对我来说)重要的是,虽然 gcc 和 clang 警告使用 作为 的参数isFlagprintf()它们都没有警告如何写入地址 0 或空指针。即使-O3 指定了 ,也能确保该isEven()函数是内联的,并且当我还指定了-Wall -Wextra.

这种情况下不应该有警告吗?

P.P*_*.P. 5

取消引用空指针是未定义的行为。不需要针对未定义的行为发出诊断(错误或警告)。因此,从标准的角度来看,不为您的示例生成任何警告是完全可以的。

\n

毫无疑问,让编译器检测它会很有用,但可能无法在所有情况下都检测到。\ngcc 确实可以检测-Wnull-dereference您的示例并生成:

\n
$ gcc -O3 -Wall -Wextra -Wnull-dereference -fsanitize=address test.c\ntest.c: In function \xe2\x80\x98main\xe2\x80\x99:\ntest.c:14:14: warning: format \xe2\x80\x98%d\xe2\x80\x99 expects argument of type \xe2\x80\x98int\xe2\x80\x99, but argument 2 has type \xe2\x80\x98int *\xe2\x80\x99 [-Wformat=]\n   14 |     printf("%d", isFlag);\n      |             ~^   ~~~~~~\n      |              |   |\n      |              int int *\n      |             %ls\ntest.c:4:17: warning: null pointer dereference [-Wnull-dereference]\n    4 |         *isFlag = 1;\n      |         ~~~~~~~~^~~\n
Run Code Online (Sandbox Code Playgroud)\n

来自海湾合作委员会文档

\n
\n

-Wnull-dereference
\n如果编译器检测到由于取消引用空指针而触发错误或未定义行为的路径,则发出警告。\n此选项仅在 -fdelete-null-pointer-checks 处于活动状态时有效,\n这是通过大多数情况下的优化启用的目标。警告的精度\n取决于所使用的优化选项。

\n
\n