Why do I get a warning when using an int variable but not when using an integer constant?

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.

1. code:

#include <stdio.h>

int main()
{
    int var = 24;

    if((!var) == NULL)
    {
        printf("1");
    }
}

2. code:

#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:

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

Answers (1)

interjay
interjay

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

Related Questions