AbhinavChoudhury
AbhinavChoudhury

Reputation: 1187

Why this redefinition of sizeof works

I'm redefining sizeof as:

#undef sizeof
#define sizeof(type)  ((char*)((type*)(0) + 1) - (char*)((type*)(0)))

For this to work, the 2 '0' in the definition need to be the same entity in memory, or in other words, need to have the same address. Is this always guaranteed, or is it compiler/architecture/run-time dependent?

Upvotes: 2

Views: 142

Answers (4)

danielschemmel
danielschemmel

Reputation: 11116

In practice, a null pointer of a certain type always refers to the same location in memory (especially when constructed the same way, as you do above), simply because any other implementation would be senseless.

However, The standard actually does not guarantee a lot about this:

  • "[...] is guaranteed to compare unequal to a pointer to any object or function." 6.3.2.3§3
  • "[...] Any two null pointers shall compare equal." 6.3.2.3§4

This leaves a lot of lee-way. Assume a memory model with two distinctive regions. Each region could have a region of null pointers (say the first 128 bytes). It is easy to see, that even in that weird case, the basic assumptions about null pointers can indeed hold! Well, given a proper compiler that makes weird null tests...

So, what else do we know about pointers in general...

What you are trying to do is first, increment a pointer

"one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)" [6.5.6§2]

and then a pointer difference

"both operands are pointers to qualified or unqualified versions of compatible complete object types" [6.5.6§3]

OK, they are (well, assuming type is a complete object type). But what about semantics?

"For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type." [6.5.6§7]

This is actually a bit of a problem: The null pointer need not point to an actual object! (Otherwise you could dereference it safely...) Therefore, incrementing it or subtracting it from another pointer is UB!

To conclude: 0 does not point to an object, and therefore the answer to your question is No.

Upvotes: 1

vonbrand
vonbrand

Reputation: 11791

A strictly standards-conforming compiler could reject this, or return some nonsense. On "typical" machines and pointers have the same size, and casting an integer to a pointer just takes that bit pattern and looks at it as a pointer. There are machines where words contain extra data (type perhaps, permission bits). Some addresses might be forbidden for certain objects (i.e., nothing can have address 0), and so on. While it is guaranteed that sizeof(char) == 1, on e.g. Crays a character is actually 32 bits.

Besides, the C standard guarantees that the expresison in sizeof(expression) is not evaluated at all, just its type is taken. I.e., ^sizeof(x++)doesn't incrementx`.

Upvotes: 0

little_birdie
little_birdie

Reputation: 5857

You are thinking that the zero's are discreet pieces of data that need to be stored somewhere. They aren't.. they are being cast as pointers to memory location zero.

When you increment a pointer to a type, it is actually incremented by the size of the type it points to. This is how C array arithmetic works.

Upvotes: 1

David Heffernan
David Heffernan

Reputation: 612914

The 0 here is not an object – it is an address. So the question you ask is something of a non-sequitur.

Upvotes: 1

Related Questions