4

Are there any ANSI C conforming environments where all-bits-zero is not a representation for a null pointer? That is, environments where the following program would print 0? If so, can you list some examples?

#include <string.h>
#include <stdio.h>

struct MyStruct {
  void *somePointer;
};

int main() {
  struct MyStruct ms;
  memset(&ms, 0, sizeof(ms));
  printf("%d\n", ms.somePointer == 0);
}

NOTE: There's some nuance here, but I'm afraid if I try to elaborate, too many people who don't carefully read the question will misunderstand and think it's similar to so many questions related to null pointers that has been asked.

math4tots
  • 8,540
  • 14
  • 58
  • 95
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/248620/discussion-on-question-by-math4tots-ansi-c-conforming-platforms-where-all-bits-z). – Samuel Liew Oct 07 '22 at 02:52

2 Answers2

4

Here are three examples of computers which have used something other than all-bits-0 for null pointers:

  • the Prime 50 series
  • the CDC Cyber 180 Series
  • some Honeywell-Bull mainframes

I can't say whether there are or were ever ANSI C compilers for these machines, however.

For further details, see question 5.17 in the C FAQ list.


Addendum: I suspect there are really two questions here:

  1. Have there actually ever been machines with nonzero null pointers?
  2. Is it safe in 2022 to write memset(&ms, 0, sizeof(ms)), as in the example in this question, and expect pointer values like ms.somePointer to come out as proper null pointers?

The answer to question 1 is undeniably "yes". (The question becomes less clear, though, if we change "Have there actually ever been" to "Are there".)

The answer to question 2 is, I think, still a matter of opinion. My own answer would be "Yes, it's safe, although I wouldn't do it, unless I was in a big hurry." That is, after memsetting all my newly-allocated C structs to 0, I still like to explicitly set any pointer fields to NULL.

But I think this is the sort of thing that every project needs to decide for itself, as part of its overall style/best practices guide. For certain issues like this one, it's still unfortunately somewhat of a judgement call whether to say "Thou shalt write 100% strictly conforming C code always", versus "We accept this practice, even though it may not be 100% strictly conforming, because we believe it should work everywhere, on any reasonable platform we care about."

Many times, saying "I believe this practice, though not guaranteed to work, should work on any reasonable platform" is quite perilous. But sometimes, it's perfectly reasonable. As I said, it can be a judgement call.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • Thank you for your answer but at the risk of being misunderstood, to add some context for my question, the motivation for my question is rooted in why the C standards committee would (1) allow `ptr=0` to set null pointers, but at the same time (2) not require that null pointers be all zero bits. If supporting platforms with non-zero bit null pointers was important, why require (1) to make implementation more awkward for compiler writers and users of such platforms when requiring users to use `NULL` could work just fine? – math4tots Oct 03 '22 at 16:13
  • @I'm sorry, but this is all very, very old ground, about which far too many redundant words have been written. Please read all of [section 5](https://c-faq.com/null/index.html) in the [C FAQ list](https://c-faq.com/), and if you still have a question, get back to me. (Also, when you get to question 5.14, note that C++ has now added a `nullptr` keyword, although IMO they [botched it](https://stackoverflow.com/questions/68804305/why-did-c11-replace-null-with-nullptr). ) – Steve Summit Oct 03 '22 at 16:16
  • In searching about this, before i asked the question, I have been aware of really old platforms that used not-all-bits-zero representations like those you mention. But it seemed like many of them actually had non-zero NULL macros as well. It just seems like the standards writers were being weirdly accommodating and also not accommodating to such platforms by having those dual requirements in the standard. I wanted to know if after the standard was ratified whether there were platforms/compilers that took advantage of this 'half-flexibility' – math4tots Oct 03 '22 at 16:17
  • "Have there actually ever been machines with nonzero null pointers?" With all due respect, definitely NOT my question. I've already known before asking the question that these have existed. I thought about including this in the question, but I was afraid of the comments section exploding... ._. – math4tots Oct 03 '22 at 16:20
  • 1
    *many of them actually had non-zero NULL macros as well* I believe this to be 100% false. `#define NULL 0` has always worked perfectly well on a machine with nonzero null pointers. – Steve Summit Oct 03 '22 at 16:22
  • Ah ok, I might have had a misunderstanding there. So even before ANSI C, was it generally accepted that NULL always expanded to `0` on basically every platform and compiler? Wouldn't it have been easier for a compiler writer to just have the macro sometimes expand to something else depending on their situation? Ok, I'm still reading the C FAQ list, once I get to the part that explains that NULL has always expanded to `0` on every platform even before there was a standard requiring it be so and why, I might come back a bit wiser ^^ – math4tots Oct 03 '22 at 16:40
  • "#define NULL 0 has always worked perfectly well on a machine with nonzero null pointers" Wait, this would depend on how the compiler was implemented and not just the platform, right? Sure after ANSI C it's guaranteed, but what about before? I had this impression that there used to be a lot of C compilers back in the day, but was that not the case? Were there just a handful of major vendors like there are today, and is that just how it worked with those major vendors? – math4tots Oct 03 '22 at 16:42
  • 3
    @math4tots When C was new, the C preprocessor was even newer, and it was optional, not trusted/used by all programmers. But knowledge of those "really old platforms" (which weren't so old then) was more widespread. So `p = 0` was a totally official way to get a null pointer, even if the bit pattern wasn't 0. But this isn't — or shouldn't be — surprising! `float f = 0` gets you a machine-dependent bit pattern that might not be all-bits-0. For that matter, saying `a = b + c` gets you a machine-dependent opcode for the `+` operator. – Steve Summit Oct 03 '22 at 16:43
  • 3
    It's the compiler's job to generate the machine-dependent bits for the higher-level constructs you write. Just about all of the confusion surrounding null pointers in C flows from Dennis Ritchie's decision to use `0` as the keyword for "null pointer" instead of something like `nullptr`. Using `0` unfortunately invites false assumptions. – Steve Summit Oct 03 '22 at 16:43
  • @math4tots *Wouldn't it have been easier for a compiler writer to just have the macro sometimes expand to something else depending on their situation?* Once upon a time, when I was a newbie, I asked more or less this exact question on comp.lang.c. It's now [question 5.10](https://c-faq.com/null/macsochange.html) in the C FAQ list. – Steve Summit Oct 03 '22 at 16:47
  • Thank you!! I'm so sorry to have such a long comment thread, but your last two comments were really especially insightful for me!! "`0` unfortunately invites false assumptions" I 100% concur! I didn't realize that's where it came from, but if the semantic lineage goes that far back, I think that makes a lot of sense to me – math4tots Oct 03 '22 at 16:48
  • "It's now question 5.10 in the C FAQ list." Huh, funny, I read that exact same page about an hour ago, but it didn't resolve all the doubt in my head that NULL still could be something else on some old platforms. But the idea that all programmers in those days having accepted `p=0` as the 'official way to get a null pointer like a widely known idiom is what sealed it for me. Because if it's widely accepted, compiler writers would be pressured to support it, even if it might have been a bit inconvenient. Or at least that's what my mind finds convincing – math4tots Oct 03 '22 at 16:55
3

It seems no POSIX compliant system would nor should output 0.

Eric Blake raised this issue in 2015 and the POSIX text was amended in 2020 by Geoff Clare to reflect that all bits zero should always be treated as a null pointer.

Read the report here: https://www.austingroupbugs.net/view.php?id=940

This is only a partial answer, as non POSIX compliant systems could still be C90 compliant and output 0. Yet such systems would cause a lot of headaches to programmers trying to port software that quietly relies on all bits zero being a valid representation of null pointers. It is quite common for structures to be allocated with calloc() and many programmers silently assume that all members of such structures are initialized to 0, which is correct for integers, but not guaranteed for floating point types (albeit true for IEEE-754 compliant systems) nor for pointer types.

chqrlie
  • 131,814
  • 10
  • 121
  • 189