sebsite

i've been thinking about null pointers

null is weird. you ever think about null pointers? because i've been thinking about null pointers.

to be clear, when i say "null is weird", i'm not talking about safety. the issue of null safety becomes almost non-existent if you use a competently designed programming language. no, i mean just, like, the entire concept of null is kinda weird.

like, you have a pointer type. it points to something. it contains the address of the thing that it points to.

but then there's one (1) value which isn't an address; it's a method of communicating a piece of semantic information.

and that information depends on the context: it's often used in C to indicate that an error occurred, or in various languages you could use it to say that a thing that could exist doesn't exist. and sometimes it communicates something else entirely, like, if you supply null to a function to tell it to allocate its own pointer rather than using a user-supplied one. and this is all conveyed with just a single value.

which leads to the other weird thing about null. the idea of pointer types in most languages is that a pointer could have any value, except for one, that being the null pointer. but anything else goes. in C in particular, the null pointer is pretty much specified as its own thing with completely different semantics than any other pointer.

the thing is, in userspace, not every pointer value is a possible address. at least on linux, 64-bit pointers only use 48 bits, so everything above 1 << 47 is invalid. i also assume that there's plenty of low values that could never be valid. so like, let's assume that a userspace pointer will never have an address lower than 0x1000.

that's a lot of different non-address values that a pointer could store! if we're already storing semantic information with null, why stop there?

i'll use a function from Hare's standard library as an example because Hare is a language i'm familiar with and it demonstrates the point i'm trying to make, but to be clear this isn't intended as a language proposal for Hare; it's just a thought experiment and maybe an idea for some other more experimental programming language:

bufio::scan_line has the return type (str | io::EOF | io::error | utf8::invalid), which is a tagged union. so the return type contains both a tag and a pointer (contained within str). but the pointer is only valid when the tag has a specific value. and all other types that could be returned are aliases of void (with the exception of io::error, which is a tagged union of void aliases, but that doesn't really change things here).

so the null pointer is used to represent an empty string, which this function could return. but we could also represent io::EOF as a "pointer" whose value is 0x1. and we could represent all the various io::error types as other pointer values that won't ever point to real things. so the tag becomes completely unnecessary, and the return type can now fit into two 64-bit registers (pointer + length).

and that's just one example. the idea is kinda like NaN boxing, except with pointers instead of floating point numbers, and also a bit more limited. the idea is basically that null already exists as a way to store some other value within a pointer type, and there's no reason null has to be more special than any of the other impossible addresses, so why not just, add more values?

idk, this is all just a thought experiment and it might be a terrible idea, null is weird