Let’s start simply with a global static variable

Although it looks like an uninitialized variable, the C language guarantees that global variables are zeroed by default. (And it’s cheap to implement, since the variables reside in well known memory, which is zeroed when allocated.)

Another step is

initialization with a constant. Piece of cake, the value will be stored written into the .data section.

Let’s get indirect

We can’t store a constant into .data section because we don’t know what the address of val will be. That’s where relocations come handy. We only reserve sufficient space in .data under given offset and add a respective relocation entry into a relocation table. Basically, the entry says: “After sections are mapped into memory, take address of val and patch it onto offset ptr_val.”

Let’s say that for some reason we want to store additional data in lower bits of a pointer variable

Trying to compile this spits the error:

No wonder, we modify the address and that operation does not fit into the relocations table, so compiler complains about non-constant expression.

As a closing note, let’s try different compiler for the mark_ptr example