Am I right that the line
if (heap_end == 0)
should be
if (heap_end == NULL)
They are exactly the same per the C standard. I personally always use 0 for null pointer initialization and checks, I never use NULL.
NULL is pretty "idiomatic" C, while 0 is more idiomatic to C++. Just curious, do you maybe have a C++ background? Just a detail.
Otherwise yes, 0 for a pointer is a null pointer in C, but I don't remember at what point it became so in the standard, I'd have to check back the history. Not convinced it was always the case.
That can be pretty confusing to some people though, so I personally don't recommend using '0'. Here is why:
0 can be used as a null pointer in C (again, don't know for sure if it was always the case in the past, or if it was borrowed from C++ as many 'new' features in C), but of course it doesn't imply that a null pointer has actually a value of zero behind the scenes, and that's what can confuse many people, even if you personally may just see it as an abstraction and don't care.
NULL has the benefit of being more "neutral" in terms of abstraction, IMHO.
One thing that can confuse people further is when it comes to casting from/to integers. As the '0' pointer may not be zero, if you cast a zero pointer to an integer, what do you get?
Given there are nasty (IMHO) implicit conversions in C all over the place, can there be nasty consequences? Maybe. Or maybe not. I know the C standard fairly well, and though I wouldn't bet a lot on this particular point without digging into the standard again.
Fear not, C23 solves it all and brings 'nullptr', which, this time, is a true pointer in terms of type, which removes any possible ambiguity with '0'.
But as a new feature, this in turn may confuse old -timers.
And given that even C99, which is 24 years old, is still not fully used by many C developers, maybe C23 will start being widely used in 2100, or something.
Oh well.