Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on What's the difference between null pointers and NULL?

Parent

What's the difference between null pointers and NULL?

+3
−1

Someone told me that I shouldn't write "NULL pointer" with capital letters, because a null pointer and NULL are different terms. And that NULL is a "null pointer constant". What's the meaning of this?

Does this have anything to do with some systems allowing a different representation of the null pointer other than zero? Can NULL be something other than zero?

History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

Post
+6
−0

There are three different, related concepts that are easy to mix up:

  • null pointers
  • null pointer constants
  • the NULL macro

Formal definitions

The first two of these terms are formally defined in C17 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.67) 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.

In other words, a null pointer is a pointer of any type pointing at a well-defined "nowhere". Any pointer can turn into a null pointer when it is assigned a null pointer constant.

The standard mentions 0 and (void*)0 as two valid null pointer constants, but note that it says "an integer constant expression with the value 0". This means that things like 0u, 0x00 and other variations are also null pointer constants. These are particular special cases that can be assigned to any pointer type, regardless of the various type compatibility rules that would normally apply.

Notably, both object pointers and function pointers can be null pointers. Meaning that we must be able to assign null pointer constants to them, no matter the actual pointer type.

NULL

The note 67) from above adds (not normative):

67) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19.

where 7.19 simply defines NULL as (normative):

NULL which expands to an implementation-defined null pointer constant;

In theory this could perhaps be something other than 0 and (void*)0, but the implementation-defined part is more likely saying that NULL can either be

#define NULL 0 or #define NULL (void*)0 or some other integer constant expression with the value zero, depending on the C library used. But all we need to know and care about is that NULL is a null pointer constant.

NULL is also the preferred null pointer constant to use in C code, because it is self-documenting and unambiguous (unlike 0). It should only be used together with pointers and not for any other purpose.

Regarding non-zero null pointers

There's quite a lot of systems that allow direct access of physical or virtual memory address zero, particularly in the context of microcontroller programming. In such cases, C does in theory allow for a null pointer with an internal representation different than zero.

If we write int* ptr = NULL; on such a system, the compiler must then realize that we are creating a null pointer, and write a suitable value to the ptr variable. It would for example be possible to write an address which would result in a hardware exception/trap in case the null-pointer is de-referenced. That is, the compiler needs to treat a null pointer as a special case, rather than declaring some exotic non-zero NULL macro.

I have never encountered such a (theoretical?) system myself. But I have encountered a whole lot of systems with a valid address zero that also used zero for the internal representation of the null pointer. Meaning that accidental null-pointer writes results in GPIO getting activated or similar nasty stuff. I've even written that particular bug myself once. The compilers for these systems are arguably non-conforming, since they violate 6.3.2.3.

Modern microcontrollers (ARM, PowerPC etc) like to map the reset vector to physical address zero. Meaning that at least you get read-only flash at that location.

History
Why does this post require moderator attention?
You might want to add some details to your flag.

1 comment thread

POSIX defines NULL as the Right Thing (4 comments)
POSIX defines NULL as the Right Thing
alx‭ wrote 7 months ago · edited 7 months ago

ISO C allows any kind of garbage in NULL, such as 0, or (void *)-1. However, POSIX mandates that it be "an integer constant expression with the value 0 cast to type void *".

This is helpful if all you care about is POSIX. Not so much if you don't.

Lundin‭ wrote 7 months ago · edited 7 months ago

alx‭ That seems to be a common misconception. 6.3.2.3 always said "An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant." With a foot note saying that NULL is a null pointer constant. What's implementation-defined about NULL is therefore if it is 0 or (void*)0 or something other boiling down to 0 such as 0UL, (false + false) etc but not -1. The C99 rationale version 5.10 clarifies NULL further (7.17).

I would be curious to know if POSIX comes with any form of rationale with sources, or if they just shoot from the hip and type stuff that sounds good because someone "heard it through the grapevine"...

alx‭ wrote 7 months ago · edited 7 months ago

7.19p3 http://port70.net/~nsz/c/c11/n1570.html#7.19p3 says "[NULL] expands to an implementation-defined null pointer constant".

I thought the text in there allows anything in NULL, and isn't restricted by 6.3.2.3p3 (which you quoted).

I interpret 6.3.2.3p3 as saying that you can use any of those literally and they'll have the meaning of a null pointer constant, but you can also use NULL, a different null pointer constant, which can expand to whatever the implementation decides to use.

Edit: But the rationale seems to say my interpretation was wrong.

alx‭ wrote 7 months ago

Regarding POSIX rationale, I don't know. Their website puts me off with several layers of registration and nonsense.