为什么在使用 int 变量时会收到警告,而在使用整数常量时却不会?

Rob*_*rtS 4 c null integer constants language-lawyer

我有一段代码的两个版本。第一种方法是使用int变量作为条件测试表达式的一部分,第二种方法是使用整数常量表示相同 - 两者都表示相同的整数值 - 24

1. 代码

#include <stdio.h>

int main()
{
    int var = 24;

    if((!var) == NULL)
    {
        printf("1");
    }
}
Run Code Online (Sandbox Code Playgroud)

2. 代码

#include <stdio.h>

int main()
{
    if((!24) == NULL)
    {
        printf("1");
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译第一个版本时,收到警告:

警告:指针和整数之间的比较

来自 gcc,和

警告:指针和整数之间的比较('int' 和 'void *')[-Wpointer-integer-compare]

从叮当。

当我使用与整数常量相同的值编译几乎等效的代码时,一切都很好。为什么?


到目前为止我的研究:

我查看了 C18 并在第 6.4.4 节“常量”中找到:

首先在小节 /2 和 /3 下:

" 2 - 每个常量都应有一个类型,常量的值应在其类型的可表示值范围内。 "

" 3 - 每个常量都有一个类型,由它的形式和值决定,稍后详述。 "。

第/5 小节下的第二个:

整数常量的类型是其值可以在其中表示的相应列表中的第一个。

以下列表:

列表

因此,没有后缀且相对于 的可表示值的整数常量24应该具有类型int


我理解警告本身并知道NULL通常在大多数实现中扩展为(void*) 0. 因此,抛出此警告是合理的。

但是为什么在使用与整数常量相同的值时不会出现警告?

int*_*jay 6

从 C11 6.3.2.3/3:

值为 0 的整数常量表达式,或转换为 void * 类型的此类表达式,称为空指针常量。

从 6.5.9/2 关于相等运算符==!=

以下之一应成立:
...
— 一个操作数是一个指针,另一个是空指针常量。

请注意,整数常量表达式不限于整数常量(0、42 等),还可以包括对它们起作用的运算符,例如5+5-10

!24是值为 0 的整数常量表达式,因此计为空指针常量。的==操作者被允许一个指针和一个空指针恒定,这使得之间作用(!24) == NULL有效的比较。

在您的第一个示例中,!var不是整数常量表达式,因为它包含一个变量操作数,因此无法与指针进行比较。

警告:在大多数实现中,NULL定义为(void*)0并且以上是正确的。但是,标准允许将其定义为任何空指针常量,例如0. 如果是这种情况,则比较(!var) == NULL将编译,因为它与(!var) == 0.