Joshua Maurice said:
So you say that *p2 is not an object? I can accept that I don't know
what
the rules are which the reason for my OP.
But in argument to what you say, consider this:
pparr p1 = (pparr)new int[3];
pparr p2= p1;
std::cout<< *p2<<std::endl;
std::cout<< typeid(*p2).name();
Is *p2 an object now?
--*p is an expression of object type. Its value is the result of a bogus
--cast, and most attempts to use that expression will run afoul of the
--strict aliasing rules.
What do you mean by bogus cast?
Does an object of array type exist ?
--An object of array type does exist yes.
What stage of the code creates the object of array type then?
Do you think new creates an non modifiable object of array type?
--You casted the result of a new expression to a "incompatible" pointer
--type. You took an expression of type "int*" and casted it to type
--"int(*)[3]".
Why do you think they are incomaptable , the pointer types both point to
the
same location.
--First. You're not guaranteed that a "int(*)[3]" has enough precision
--to store a int*. You may lose precision. It may be "rounded".
It doesn't strore an int* it stores a value. A pointer value is a memory
address.
The memory address for an int and an array of integers is the same.
--Incorrect. On some obscure C++ implementations, sizeof(void*) is
--greater than sizeof(int*). The reason is that the underlying machine
--is only 64 bit addressable, but they wanted CHAR_BITS to be 8, that is
--they wanted char* to address units of 8 bits. Thus, most C++ pointers
--in that implementation are hardware addresses that address 64 bit
--units, but char pointers (and thus void pointers) actually are a bit
--more. They stored the address of the 64 bit unit, and they stored an
--offset into that 64 bit unit, to allow the user to code C++ code with
--char pointers that addressed 8 bit units.
But a pointer to an array of T's is the same type as a pointer to a T. So a
pointer to an array of array of T's would be the same size.
This would only be a problem if you cast from pointer to T to pointer to U.
--Also, with high gcc optimization, you may actually see its strict
--aliasing optimizations break your code. It's allowed to assume that
-- int* x;
-- int (*y)[3];
--do not alias, and it in fact assumes that they do not alias, and it
--reorders reads and writes as part of optimization according. Do some
--research on strict aliasing. My favorite resource on this topic is:
--http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
I never tried gcc.
--Second, any attempt to use a dereference of the "int(*)[3]" pointer.
--will be undefined behavior. You obtained it improperly, that is
--through a reinterpret_cast (or equivalent C-style cast), and there are
--no exceptions that would make this allowed, that would make this not
--undefined behavior. Thus that code will run afoul of the strict
--aliasing rules "C++03, 3.10 Lvalues and rvalues / 15" and have
--undefined behavior.
So any reinterpret cast in C++ results in UB?
--Pretty much, yeah. There's some important and notable exceptions (such
--as: casting to char or unsigned char*, or conversions between pointers
--of sufficient size and alignment, or conversions between pointers and
--integers of sufficient size, conversions between a pointer to POD-
--struct and a pointer to its first element), but let's just say for the
--moment that most uses reinterpret_cast produce UB.
Well I know my cast is pretty well defined on most normal desktop pc's and
for the sake of this discussion that is acceptable. I could add some checks
if it were production code but its not necessary for simple example code
snippets.