Reputation: 15042
I have two versions of a piece of code. The first is by using an int
variable as part of an expression for a condition test, the second by using an integer constant for the same - both represent the same integral value - 24
.
#include <stdio.h>
int main()
{
int var = 24;
if((!var) == NULL)
{
printf("1");
}
}
#include <stdio.h>
int main()
{
if((!24) == NULL)
{
printf("1");
}
}
When I attempt to compile the first version, I get the warning:
warning: comparison between pointer and integer
from gcc, and
warning: comparison between pointer and integer ('int' and 'void *') [-Wpointer-integer-compare]
from clang.
When I compile the almost equivalent code by using the same value just as integer constant, everything is fine. Why?
My research so far:
I looked into C18 and found on section 6.4.4 "Constants":
First under Subsection /2 and /3:
"2 - Each constant shall have a type and the value of a constant shall be in the range of representable values for its type."
"3 - Each constant has a type, determined by its form and value, as detailed later.".
And second under Subsection /5:
"The type of an integer constant is the first of the corresponding list in which its value can be represented."
The following list:
Thus, an integer constant with no suffix and relative to the representable value of 24
should have type int
.
I understand the warning itself and know that NULL
usually on most implementations expands to (void*) 0
. Thus, it is reasonable that this warning is thrown.
But why does the warning not occur when using the same value as integer constant?
Upvotes: 4
Views: 230
Reputation: 110108
From C11 6.3.2.3/3:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
And from 6.5.9/2 regarding equality operators ==
and !=
:
One of the following shall hold:
...
— one operand is a pointer and the other is a null pointer constant.
Note that integer constant expressions are not limited to integer constants (0, 42, etc.) but can also include operators acting on them like 5+5-10
.
!24
is an integer constant expression with the value 0, and therefore counts as a null pointer constant. The ==
operator is allowed to act between a pointer and a null pointer constant, which makes (!24) == NULL
a valid comparison.
In your first example, !var
is not an integer constant expression because it includes a variable operand, and thus cannot be compared with a pointer.
Caveat: In most implementations, NULL
is defined as (void*)0
and the above is correct. However, the standard allows it to be defined it as any null pointer constant such as 0
. If this is the case, then the comparison (!var) == NULL
will compile because it is the same as (!var) == 0
.
Upvotes: 6