Frederick,
Let me develop the subject a little bit so we can understand your intent.
We have two types of information we are dealing with in this thread.
We have
1- the pointer as a value
and
2- the memory the pointer points to.
T* p = new T{};
'p' is a variable of type pointer to 'T', it occupies sizeof(T*) in memory and is aligned at alignof(T*).
But the memory where 'p' points to, is placed at alignof(T) boundaries in memory, and it occupies sizeof(T) in memory.
Also we have, sizeof (void*) >= sizeof(T*), true for each platform. Because we can cast back and forth between void* and the pointer type of origin.
'void*' is a general purpose pointer type, for idempotent cast operations.
sizeof(void*) >= sizeof(T*), means when you cast between T* and void*, there is no data loss, or data creation.
i.e:
Iet say:
T* ptr;
void* vptr = static_cast<void*>(ptr);
If :
Case 1- sizeof(void*) < sizeof(T*) then the value of ptr is truncated to fit inside vptr => data loss.
Expl:
ptr = 0x0000FFFF954729A0;//sizeof(T*) ==8
vptr = (void*)(ptr); //if for expl sizeof(void*)==4
// => vptr=0x954729A0
// then casting back
ptr = (T*)(vptr); //ptr = 0x00000000954729A0
^^^^^^data loss
Case 2- sizeof(void*) > sizeof(T*) then some extra bit get appended to ptr to fill vptr => data creation.
Expl:
ptr = 0x954729A0;//sizeof(T*) ==4
vptr = (void*)(ptr); //if for expl sizeof(void*)==8
// => vptr=0x00000000954729A0 =>added 0s
// then casting back
ptr = (T*)(vptr); //ptr = 0x954729A0
Here we are safe, because we got our original value back, but at a cost, this cost is some extra CPU instructions:
xor reg, reg // zero out register before. // assignment
mov reg, valueOf(ptr);
Instead of directly:
mov reg, valueOf(ptr) // same size => direct. // assignement.
Now the other side of the coin: the memory type.
Given the following:
char arr[4];
char* Elem4 = arr + 3;
If for expl on some platform sizeof(char*)==4,
and alignof(char)==1:
arr = 0x954729A[0];
Elem4 = 0x954729A[3]; //observe alignment
If you want to do the following:
int* correctPtr = static_cast<int*>(arr);
int* wrongPtr = static_cast<int*>(Elem4);
*correctPtr; // dereferencing at a correct // alignment of int is perfectly legal
*wrongPtr; // dereferencing at a wrong. // alignment of int => UB.
// int cannot be stored/loaded. // at/from an odd memory value
That's the essence of strict aliasing rule.
So in conclusion, most platforms makes sizeof(void*) big enough to fit any T* in it without losing data, and on the other side reducing the sizeof(T*), will mean that, certain memory regions are not accessible for allocating T, so usually what they do is: sizeof(void*)==sizeof(T*), for all T.
Imposing on implementations to make all T* of same size, will prevent some techniques,
For example, if on some platforms sizeof(char*)=2, and sizeof(void*)=4, you can use the exra-word to store some data, then when finished, you cast back char* without losing the original address value.
But also, it is impractical to bookkeeping pointer sizes for many types.
Overall, what you are asking for is doable, since it is aleady in use, but i guess maybe some legacy code is preventing it.
If that's not what you meant, please enlighten us.
-------- Original message --------
From: Sebastian Wittmeier via Std-Proposals <std-proposals@lists.isocpp.org>
Date: 1/27/25 11:55 AM (GMT+01:00)
To: std-proposals@lists.isocpp.org
Cc: Sebastian Wittmeier <wittmeier@projectalpha.org>
Subject: Re: [std-proposals] Make all data pointers intercompatible
So you want to abolish alignment? And allow full type-aliasing? And with it abolish object lifetimes?
So you cannot copy the byte-representation to a local variable and back, because the object points to itself?
And you cannot use theoretical memory access functions, which can access misaligned memory, as the memory access could happen inside a member function? So you want to run member functions on misaligned memory?
Perhaps one could use or introduce relative pointers instead, similar to pointers to members?
If a class uses those, it could more likely be trivially copied?
-----Ursprüngliche Nachricht-----
Von: Frederick Virchanza Gotham via Std-Proposals <std-proposals@lists.isocpp.org>
Tiago wrote:
>
> So what is the point of this?
I want C++26 to explicitly state: "All pointer types are
intercompatible -- they all have the same size and representation",
which would allow code like:
char c;
long double *p = &c;
char *p2 = p;
*p2 = 'a';
The main use for this would be in allowing data to be misaligned in
memory. For example let's consider "std::basic_string<char32_t>" which
contains a pointer into its own buffer. If such an object is
misaligned in memory, then the pointer into the buffer might not
accurately point at the buffer. But I want the Standard to be changed
so that all pointers are the same.
There were rumours years and years ago of systems that had different
size pointers but they're all extinct now.