Could it be the case that sizeof(T*) != sizeof(const T*)?

C++Language Lawyer

C++ Problem Overview


I'm arguing with my boss about this. They say "Yes they can be different."

Is it possible that sizeof(T*) != sizeof(const T*) for a type T?

C++ Solutions


Solution 1 - C++

No, they can't be different. For sufficiently different T1 and T2, sizeof(T1 *) can be different from sizeof(T2 *), but if T2 is just const T1, then:

> 3.9.2 Compound types [basic.compound]

> 3 [...] Pointers to cv-qualified and cv-unqualified versions (3.9.3) of layout-compatible types shall have the same value representation and alignment requirements (3.11). [...]

And any type T is layout-compatible with itself:

> 3.9 Types [basic.types]

> 11 If two types T1 and T2 are the same type, then T1 and T2 are layout-compatible types. [...]


Value representation is in relation to the object representation, you can't have the same value representation without also having the same object representation. The latter means the same number of bits is required.

> 3.9 Types [basic.types]

> 4 The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.44

> 44) The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C.

The point of the requirement, the reason it doesn't just say that the two types have the same object representation, is that T * and const T * not only have the same number of bits, but also that it's the same bits in T * and const T * that make up the value. This is meant to guarantee not only that sizeof(T *) == sizeof(const T *), but it means even that you can use memcpy to copy a T * pointer value to a const T * pointer value or vice versa and get a meaningful result, the exact same result you would get with const_cast.

The alignment requirements provide some additional guarantees too, but they're complicated to explain properly and not directly relevant to this question, and there are issues in the standard that undermine some of the intended guarantees, so I think that's best left ignored here.

Solution 2 - C++

Microchip released such a C compiler where the sizeof(T*) was 2 but sizeof(const T*) was 3.

The C compiler was not standards-compliant in a few ways, so this says nothing about this being valid (I suspect it isn't and other answers agree).

Solution 3 - C++

Hmm, this is highly esoterical, but I'm thinking that theoretically there could be an architecture which has, say, 256 bytes of RAM in address 0 and, say, some kilobytes of ROM in higher addresses. And there could be a compiler that would create a 8-bit pointer for int *i because 8 bits is enough to hold the address of any object in the highly limited RAM area and any mutable object of course is implicitly known to be in the RAM area. Pointers of type const int *i would need 16 bits so that they could point to any location in the address space. The 8-bit pointer int *i is castable to a 16-bit pointer const int *i (but not vice versa) so the castability requirement of C standard would be satisfied.

But if there's such an architecture in existense, I'd sure like to see it (but not write code for it) :)

Solution 4 - C++

As far as standard C++ is concerned, they cannot differ. C and C++ are similar on this point.

But there are many architectures out there with compilers written for them that do not follow this rule. Indeed then we are not really talking about standard C++, and some folk would argue then that the language is not C++, but my reading of your question (prior to the addition of the language lawyer tag) is more about the possibility.

In which case, it is possible. You may well find that a pointer to ROM (therefore const) is a different size to a pointer to RAM (const or non const.)

If you know for sure that your code will only wind up on a standards complaint compiler then your assumption is correct. If not, then I'd think carefully about relying on their sizes being the same.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionP45 ImminentView Question on Stackoverflow
Solution 1 - C++user743382View Answer on Stackoverflow
Solution 2 - C++JoshuaView Answer on Stackoverflow
Solution 3 - C++PkPView Answer on Stackoverflow
Solution 4 - C++BathshebaView Answer on Stackoverflow