Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to assume that the NULL constant is zero?

The book Understanding and Using C Pointers, by Richard Reese says:

The null concept is an abstraction supported by the null pointer constant. This constant may or may not be a constant zero. A C programmer need not be concerned with their actual internal representation.

My question is, since "this constant may or may not be a constant zero," is it safe for me to do things like the below in my code:

int *ptr = NULL;
// Some code which probably sets ptr to a valid memory address

if(!ptr)
{
   ERROR();
}

If NULL is not 0, there is a chance that the if clause will evaluate to true.

like image 280
the_endian Avatar asked Mar 20 '20 03:03

the_endian


People also ask

IS null always defined as 0?

The null pointer constant is always 0. The NULL macro may be defined by the implementation as a naked 0 , or a cast expression like (void *) 0 , or some other zero-valued integer expression (hence the "implementation defined" language in the standard). The null pointer value may be something other than 0.

IS null same as 0 in C?

NULL is 0 . NULL should be used with pointers, not integers.

What is the function of the null constant?

A null pointer constant is an integer constant expression that evaluates to zero. For example, a null pointer constant can be 0, 0L , or such an expression that can be cast to type (void *)0 .

IS null always false?

Comparing any variable with NULL will always evaluate to FALSE, regardless if it's value, unless IS NULL or IS NOT NULL is used. Violating this rule will affect the functionality of the code. The severity is critical which means that the code will not function correctly.


1 Answers

Is it safe to assume that the NULL constant is zero?

NULL will compare equal to 0.
NULL is very commonly a zero bit pattern. It is possible for NULL to be a non-zero bit pattern - but not seen these days.


OP is mixing as least 4 things: NULL, null pointer constant, null pointer, comparing a null pointer to 0. C does not define a NULL constant.

NULL

NULL is a macro "which expands to an implementation-defined null pointer constant" C17dr § 7.19 3

null pointer constant

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

Thus the type of a null pointer constant may be int, unsigned, long, ... or void * .

When an integer constant expression1, the null pointer constant value is 0. As a pointer like ((void *)0), its value/encoding is not specified. It ubiquitously does have the bit pattern of zeros, but is not specified so.

There may be many null pointer constants. They all compare equal to each other.

Note: the size of a null pointer constant, when it is an integer, may differ from the size of an object pointer. This size difference is often avoided by appending a L or two suffix as needed.

null pointer

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. C17dr § § 6.3.2.3 3

Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal. C17dr § § 6.3.2.3 4

The type of null pointer is some pointer, either an object pointer like int *, char * or function pointer like int (*)(int, int) or void *.

The value of a null pointer is not specified. It ubiquitously does have the bit pattern of zeros, but is not specified so.

All null pointer compare as equal, regardless of their encoding.

comparing a null pointer to 0

if(!ptr) is the same as if(!(ptr != 0)). When the pointer ptr, which is a null pointer, is compared to 0, the zero is converted to a pointer, a null pointer of the same type: int *. These 2 null pointers, which could have different bit patterns, compare as equal.


So when it is not safe to assume that the NULL constant is zero?

NULL may be a ((void*)0) and its bit pattern may differ from zeros. It does compare equal to 0 as above regardless of its encoding. Recall pointer compares have been discussed, not integer compares. Converting NULL to an integer may not result in an integer value of 0 even if ((void*)0) was all zero bits.

printf("%ju\n", (uintmax_t)(uintptr_t)NULL); // Possible not 0

Notice this is converting a pointer to an integer, not the case of if(!ptr) where a 0 was converted to a pointer.

The C spec embraces many old ways of doing things and is open to novel new ones. I have never came across an implementation where NULL was not an all zeros bit pattern. Given much code exist that assumes NULL is all zero bits, I suspect only old obscure implementations ever used a non-zero bit-pattern NULL and that NULL can be all but certain to be an all zero bit pattern.


1 The null pointer constant is 1) an integer or 2) a void*. "When an integer ..." refers to the first case, not a cast or conversion of the second case as in (int)((void*)0).

like image 86
chux - Reinstate Monica Avatar answered Sep 21 '22 19:09

chux - Reinstate Monica