ISO C3X proposal: nonnull qualifier

Hi,

I love C programming (I’ve been doing it for 23 years) and I think something like your idea would be a great addition to the language. I was already thinking about this topic extensively since Friday, including all the possible ways to introduce ‘null’/‘non-null’ type qualifiers.

It seems to me that the only way of adding nullability information to C’s type system that is sympathetic to the language’s syntax, and allows the information to be added to programs gradually without breaking compatibility, would be to create a pointer target type qualifier like ‘const’. Putting the type qualifier on the pointer type (like ‘restrict’) is just wrong IMO.

My idea is simply to add a new pointer target type qualifier, analogous to 'const’​, except that the new qualifier would mean “the address of this object may be a null pointer”. It would have the same syntax and usage rules as 'const’​ (unlike, say, C++ references):

int optional *x = NULL;
int *y = x; // compiler error
int optional *z = x; // okay

That would allow people to annotate which parts of their code can safely handle null pointer values, in the same way that they can already annotate which parts of their code can safely handle addresses of immutable objects. I think this idea is equally applicable to C and C++, and wouldn’t upset people who dislike C++ syntax, nor fall into the trap of “implementing C++ in C”.

I thought the new qualifier could be called ‘optional’ by analogy with the Python type annotation of the same name. This avoids clashing with the names of existing Clang annotations such as _Nullable ​ or _Nonnull ​ which aren’t part of the language’s type system and seem only to be understood by Clang-format. (Those annotations are also less strict and more complex than what I envisaged.)

My choice of name also puts mental space between pointer type qualifiers that are implicitly discarded on copy (such as ‘restrict’) and my proposed pointer target type qualifier, which cannot be discarded on copy (like 'const’​). In other words, it’s a statement about the object, not the address of the object:

int optional q = 4;
int r = q; // okay

Since optional isn’t a reserved word, it would need to be defined as a macro alias for an inbuilt name like _Optional`​ in a header file (e.g. a header named <stdopt.h> ​ by analogy with <stdbool.h>​)

Existing code could easily be updated progressively​:

  • functions which consume pointers that can be null could be changed with no effect on compatibility. For example, void free(void optional *) ​ could consume a pointer to an optional​-qualified type, or a pointer to an unqualified type, without casting.
  • ‘Safe’ variants of functions which produce pointers could also be written, e.g.

void optional *malloc(size_t);

would produce a pointer that can only be passed to functions which accept optional-qualified pointer target types. Crucially, however, this is not necessary! Assigning the return value of standard malloc() ​ to an object of any pointer-to-optional type would be sufficient to ensure that it cannot be used with any interface (or local variable) which doesn’t promise to handle a null value safely.

I don’t envisage that a language standard would mandate that compilers statically check for unchecked dereferences of pointers to ‘optional’ types, but they would acquire the ability to do:

extern int optional *z;
if (z != NULL) ++z; // okay (based on usage)
++z; // optional compiler warning (based on usage)