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
It's a long story. Once upon a time, there were three ways to express a null pointer constant: NULL 0 ((char *) 0) This was true at least as far back as Unix V7 (1979). Maybe even further...
Answer
#10: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL (due to some irrational aversion to macros), and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix V7 (1979). Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL (due to some irrational aversion to macros), and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#9: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL (due to some irrational fear of macros), and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL (due to some irrational aversion to macros), and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#8: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL, and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL (due to some irrational fear of macros), and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#7: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, C++ avoided using NULL, and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, most C++ code avoided using NULL, and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#6: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. In fact, C++ avoided using NULL, and decided to stick with the absolute worst possible null pointer constant: `0`. See <https://www.stroustrup.com/bs_faq2.html#null>. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#5: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature in C23 cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#4: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
One co-author of the paper that introduced `nullptr`, n3042, wrote the following:- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr` in C23, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#3: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr`, n3042, wrote the following:
> Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr`, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- >
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- >
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#2: Post edited
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
The author of the paper that introduced `nullptr`, n3042, wrote the following:- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
Very quickly, the vendor agreed with the arguments, and changed their implementation. The author of the paper had to fulfill its promise, and raise a Nation Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
- It's a long story.
- Once upon a time, there were three ways to express a null pointer constant:
- - `NULL`
- - `0`
- - `((char *) 0)`
- This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand.
- `void *` still didn't exist. `NULL` itself resolved to one of the other two.
- Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`.
- Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way.
- `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *".
- However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades.
- In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one.
- After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C.
- At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on.
- Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C.
- In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL.
- <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>.
- One co-author of the paper that introduced `nullptr`, n3042, wrote the following:
- > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge:
- > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well.
- > Good luck to the person who signed up for this.
- I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition.
- <https://github.com/cc65/cc65/issues/1823>
- Very quickly, the vendor agreed with the arguments, and changed their implementation. The co-author of the paper had to fulfill its promise, and raise a National Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23.
- <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm>
- (search for `NEN/NL5`).
- From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid:
- - Compatibility with C++
- Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++.
- - _Generic.
- The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse.
- - Vendors refusing to fix their implementation.
- Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.
#1: Initial revision
It's a long story. Once upon a time, there were three ways to express a null pointer constant: - `NULL` - `0` - `((char *) 0)` This was true at least as far back as Unix v7. Maybe even further back in time; I don't have older Unix sources at hand. `void *` still didn't exist. `NULL` itself resolved to one of the other two. Over time, `void *` was invented, and started to be used. However, it was still recent enough that it wasn't considered as written in stone. The `((char *) 0)` null pointer constant started to be replaced by `((void *) 0)`. Then C++ was invented, and questioned the goodness and safety of the new `void *`, as it could be used to circumvent type safety. C++ decided that instead of allowing 2-way conversions, it would only allow one way. `0` had been an unsafe null-pointer constant, especially in variadic function calls. And even in other places it was quite unreadable, as it could be easily confused with an integer 0. Eventually, C moved into using NULL everywhere, and defining NULL as `((void *) 0)`, with only residual cases of the older `0`. And that use was eventually standardized into the POSIX definition of NULL, which requires that it is defined as "the value 0 cast to type void *". However, C++ had already forked their idea of `void *` with distinct implicit conversions, which meant they couldn't use this better definition of NULL (it wouldn't implicitly convert to any other pointer, which is a key feature of a null pointer constant). C++ had to stick to the worst possible null pointer constants: either a literal `0`, or a `NULL` that would itself expand to `0`. Ironically, in their attempt to have a safer language, they had an unsafer null pointer constant, for decades. In the C world, almost everybody had moved to the right definition of NULL. Only a few groups had stayed with the old `#define NULL 0`, and only because they hadn't really reasoned about it too much. For that reason, ISO C still allowed the low-quality definition of NULL; even though mostly every vendor had the good one. After several decades of having a broken set of null pointer constants, C++ decided to fix their self-inflicted bug. C++11 invented `nullptr` (and `nullptr_t`). C didn't care at all, because it was not a problem in C. At some point, some people raised the false premise that C code using NULL was unsafe, because it was allowed to be defined to `0`. The right thing to do would have been to follow POSIX, and require in ISO C that `NULL` be defined as `((void *) 0)`. That would have required a little bit of work, talking to those implementations that had the bad definition, and convince them to move on. Those people didn't feel like doing that job, and had also some conflict of interest, since they were proponents of a common core between C++ and C, being (also) C++ programmers. Members of the C standard committee (WG14) proposed something that was less work: pick C++'s nullptr in C. In the end, the feature was voted into the standard, mainly by C++ proponents, and some pressure by a few proprietary compiler vendors that didn't want to fix their broken NULL. <https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3042---introduce-the-nullptr-constant>. The author of the paper that introduced `nullptr`, n3042, wrote the following: > Someone recently challenged me, however: they said this change is not necessary and bollocks, and we should simply force everyone to define NULL to be void*. I said that if they’d like that, then they should go to those vendors themselves and ask them to change and see how it goes. They said they would, and they’d like a list of vendors defining NULL to be 0. Problem: quite a few of them are proprietary, so here’s my Open Challenge: > if you (yes, you!!) have got a C standard library (or shim/replacement) where you define NULL to be 0 and not the void-pointer version, send me a mail and I’ll get this person in touch with you so you can duke it out with each other. If they manage to convince enough vendors/maintainers, I’ll convince the National Body I’m with to write a National Body Comment asking for nullptr to be rescinded. Of course, they’ll need to not only reach out to these people, but convince them to change their NULL from 0 to ((void*)0), which. Well. > Good luck to the person who signed up for this. I did my work, and researched which open-source implementations were really defining NULL as `0`. I could only find exactly one. I talked to them, and gave arguments of why it would be reasonable to fix their definition. <https://github.com/cc65/cc65/issues/1823> Very quickly, the vendor agreed with the arguments, and changed their implementation. The author of the paper had to fulfill its promise, and raise a Nation Body Comment against its own paper, soliciting the removal of `nullptr` from C23. However, C++ proponents in WG14 voted in favor of ignoring the comment (not even giving reasons, other than not wanting to question again the topic), and the feature stayed in C23. <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3077.htm> (search for `NEN/NL5`). From the reasons that the papers that added the feature cited, let's break them down, and explain why they were invalid: - Compatibility with C++ Code using `NULL` had always been valid C++. And C++ could `#define NULL nullptr`, if they really cared about C/C++ compatibility. They never cared about that, and thus never did. C++ considers C to be a misdesigned language that can only be fixed by making it be C++. - _Generic. The paper says that having nullptr be of type `nullptr_t` would be better for _Generic, because it would allow behaving differently for a null pointer constant input. But why should a function behave differently for a null pointer constant than for a run-time null pointer? That makes no sense at all. Also, _Generic selections would still have to take care of users passing `NULL`, after all, so it's just duplicating the number of branches that have to be written, making it worse. - Vendors refusing to fix their implementation. Did anybody really try? I mean, with good arguments? I have doubts. It only took me a few days to fix the only FOSS vendor that we could find. If anyone gives me the address of the maintainers of the proprietary (undisclosed) vendors that refused to do so, I'll try to convince them. Nobody gave me their addresses. I think ISO should have just told them to upgrade or die; or assume that they would not conform to C23.