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.
Post History
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 C1...
Answer
#4: Post edited
- 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_.<sup>67)</sup> 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):
- > <sup>67)</sup> 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 system 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.
- 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_.<sup>67)</sup> 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):
- > <sup>67)</sup> 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.
#3: Post edited
- 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_.<sup>67)</sup> 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):
- > <sup>67)</sup> 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 system 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. I've written that particular bug even. 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.
- 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_.<sup>67)</sup> 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):
- > <sup>67)</sup> 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 system 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.
#2: Post edited
- 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_.<sup>67)</sup> 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):
- > <sup>67)</sup> 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 system 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. I've written that particular bug even. 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.
- 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_.<sup>67)</sup> 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):
- > <sup>67)</sup> 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 system 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. I've written that particular bug even. 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.
#1: Initial revision
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_.<sup>67)</sup> 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): > <sup>67)</sup> 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 system 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. I've written that particular bug even. 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.