Is ((void*)0) a null pointer constant?

what is (void*)0 in c
void*0 in c
null pointer in c
a pointer is
what is (void*)0 mcq
how to check if a pointer is null in c
what is null constant in java
null pointer example

I'm reading this blog post and under the section Null pointer constants and parenthesized expressions the author references § 6.3.2.3 and § 6.5.1 from the ISO C standard and says:

It doesn't say that a parenthesized null pointer constant is a null pointer constant.

Which implies, strictly speaking, that (void*)0 is a null pointer constant, but ((void*)0) is not.

Then:

I'm sure that most C implementations do treat a parenthesized null pointer constant as a null pointer constant, and define NULL either as 0, ((void*)0), or in some other manner.

The two referenced sections say:

§ 6.3.2.3

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

§ 6.5.1

A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.

Doesn't the bolded sentence contradict the author's claim that ((void*)0) is not a null pointer constant?

Doesn't the bolded sentence contradict the author's claim that ((void*)0) is not a null pointer constant?

No, it doesn't. (I confess to being a bit biased, since the referenced blog is mine.)

The bolded sentence says that its type and value are identical to those of the unparenthesized expression. That's not enough to imply that it's a null pointer constant.

Consider:

void *var = 0;

(void*)0 is a null pointer constant. ((void*)0) has the same type and value as (void*)0. var also has the same type and value as (void*)0, but var clearly is not a null pointer constant.

Having said that, I'm 99+% sure that the intent is that ((void*)0) is a null pointer constant, and more generally that any parenthesized null pointer constant is a null pointer constant. The authors of the standard merely neglected to say so. And since the description of parenthesized expressions in 6.5.1p5 specifically enumerates several other characteristics that are inherited by parenthesized expressions:

A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.

the omission is troubling (but only mildly so).

But let's assume, for the sake of argument, that ((void*)0) is not a null pointer constant. What difference does it make?

(void*)0 is a null pointer constant, whose value is a null pointer of type void*, so by the semantics of parenthesized expressions ((void*)0) also has a value that is a null pointer of type void*. Both (void*)0 and ((void*)0) are address constants. (Well, I think they are.) So what contexts require a null pointer constant and do not accept an address constant? There are only a few.

6.5.9 Equality operators

An expression of function pointer type may be compared for equality to a null pointer constant. (An object pointer may be compared to an expression of type void*, but a function pointer may not, unless it's a null pointer constant.) So this:

void func(void);
if (func == ((void*)0)) { /* ... */ }

would be a constraint violation.

6.5.16.1 Simple assignment

In an assignment, a null pointer constant may be assigned to an object of pointer-to-function type, and will be implicitly converted. An expression of type void* that's not a null pointer constant may not be assigned to a function pointer. The same constraints apply to argument passing and initialization. So this:

void (*fp)(void) = ((void*)0);

would be a constraint violation if ((void*)0) were not a null pointer constant. Thanks to commenter hvd for finding this.

7.19 Common definitions <stddef.h>

The macro NULL expands to "an implementation-defined null pointer constant". If ((void*)0) is not a null pointer constant, then this:

#define NULL ((void*)0)

would be invalid. This would be a restriction imposed on the implementation, not on programmers. Note that this:

#define NULL (void*)0

is definitely invalid, since macro definitions in standard headers must be fully protected by parentheses where necessary (7.1.2p5). Without the parentheses, the valid expression sizeof NULL would be a syntax error, expanding to sizeof (void*) followed by an extraneous constant 0.

Is ((void*)0) a null pointer constant?, It must be defined before use. Null pointer constants. 0. You can use an integer constant expression with the value 0 or an expression that is cast to (void *)0� “An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

It is a parenthesized expression which contains a null pointer constant, so it indisputably is a null pointer value. Using it as an rvalue has exactly the same effect as using the "compliant" version as an r-value.

If there were some syntactic rules that could only accept a null pointer constant, it would not qualify. But I'm not aware of any (though I'm less expert on C).

And while neither one is a constant (referring to the formal grammar production), both can appear in a constant expression in an initializer, because both null pointer constants and address constants are allowed, and a constant null pointer value is explicitly included in the category of address constant.

Pointer comparisons also specifically mention null pointer constants... but here pointer values are also accepted, and all null pointer values are treated equally. Same for the ternary and assignment operators.

Please do be aware that these rules are quite different in C++, where both the above expressions are constant null pointer values of type void*, but not universal null pointer constants. Null pointer constants in C++ are integral constant expressions which evaluate to zero. And void* doesn't implicitly convert to other pointer types.

Null pointers, A null pointer has a reserved value that is called a null pointer constant for indicating can be 0, 0L , or such an expression that can be cast to type (void *)0 . A null-pointer constant is an integral constant expression that evaluates to zero (like 0 or 0L), or the cast of such value to type void* (like (void*)0).

Try printing below line in your C code:

printf("%p",(void*)0);

You will get the output as:

(nil)

NULL pointer in C, Coming to our discussion, NULL macro is defined as ((void *)0) in header files But C standard is saying that 0 is also a null pointer constant. The new null pointer nullptr cleans up in C++ with the ambiguity of the number 0 and the macro NULL. The number 0. The issue with the literal 0 is that is can be the null pointer (void*)0 or the number 0. This is up to the context. I admit, we are used to this oddity. But only almost.

What is the difference between a pointer pointing to 0x0 location and , h> and several other standard headers, that expands to an implementation- defined null pointer constant. The expansion is typically either 0 or ((void*)0) (the outer� Description. The C library Macro NULL is the value of a null pointer constant. It may be defined as ((void*)0), 0 or 0L depending on the compiler vendor.. Declaration. Following may be the declaration for NULL Macro depending on the compiler.

Null pointer, In computing, a null pointer or null reference has a value saved for indicating that the pointer or There are occasions when dereferencing the pointer to address zero is intentional and However, C++11 has introduced the explicit null pointer constant nullptr to be used instead. In Eiffel, it is called a void reference. Which implies, strictly speaking, that (void*)0 is a null pointer constant, but ((void*)0) is not. Then: I'm sure that most C implementations do treat a parenthesized null pointer constant as a null pointer constant, and define NULL either as 0, ((void*)0), or in some other manner. The two referenced sections say: § 6.3.2.3

Migrating from C to C++: NULL vs nullptr, //Possible implementation #define NULL 0 //since C++11 #define NULL If a null pointer constant has integer type, it may be converted to a If you invoke f(NULL ) , you will enter the f(int) function rather than the f(int *) function like you types void foo(std::nullptr_t); //specialized overload for nullptr value� MISRA-C++ Rule 4-10-2 (required): Literal zero (0) shall not be used as the null-pointer-constant. Now, if numShots were a "real" pointer I could have changed 0 to NULL . But numShots is reference and I should treat it as it was an int .

Comments
  • I've taken the liberty of adding the "language-lawyer" tag. (And it's nice to know someone actually reads my blog!)
  • Related Is it possible to have a pointer literal?
  • One detraction: making your argument run through void* var has the weakness that var is not a null pointer constant because it also happens not to be an ICE.
  • Can you elaborate a bit on what "not a null pointer constant" means? I mean, var isn't one because it isn't a constant, but what does it mean for ((void*)0) not to be one? Is there any sort of perverse compiler behavior that is technically allowed by the spec due to this oversight?
  • @KeithThompson 6.3.2.3 Clause 4: Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
  • Just musing, the previous sentence says "if a null pointer constant is converted to a pointer type, the resulting pointer [is] called a null pointer". A strict reading might suggest that weird need not be a null pointer at all, if that conversion does not happen because ((void*)0) is not a null pointer constant in the first place. And if weird is not a null pointer, then it need not compare equal to one. Naturally this is all nonsense if the act of adding parentheses to (void*)0 itself constitutes a conversion to a pointer type, which it likely does if ((void*)0) is of pointer type.
  • Merely converting ((void*)0) to a pointer-to-function type is enough to demonstrate the problem, even without any comparisons: void (*fp)(void) = ((void*)0); is valid if and only if ((void*)0) is a NPC. Perhaps also interesting is that C++ has replaced the semantics of parentheses with a much simpler one: "The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used, and with the same meaning, except as otherwise indicated." This also affects, for example, char str[] = ("abc");, which is valid in C++ but not in C.
  • How is "neither [(void*)0 or ((void*)0)] one a constant"? The standard claims explicitly that (void*)0 is a null pointer constant.
  • @IwillnotexistIdonotexist: There is a grammar production for constant which includes only integer-constant, floating-constant, enumeration-constant, and character-constant. These pointer values are constant expressions, but not constants. Your concept that the word "constant" encompasses every sort of integer constant, address constant, null pointer constant, and so on just doesn't hold here; the usual rules of the English language do not apply, the formal grammar does.
  • Perhaps you could then disambiguate that use of constant as "And while neither one is a syntactical constant, both can..."?
  • It turns out there is at least one context where a null pointer constant is permitted but ((void*)0), if it weren't an NPC would not be. An expression of pointer-to-function type may be compared for equality or inequality to a null pointer constant, but not to any other constant expression of type void*. See my updated answer for details.
  • Which you'll also get for (char*)0, or (void*){0} but (char*)0 and (void*){0} aren't null pointer constants while (void*)0 is.