Lets put it another way

P

Paul

typeid does not require an object but when it is passed an object it gives
us the type of that object.

Only if the static type of the expression is polymorphic. Ex:

int x;
typeid(x);
will say int.

int x;
char* c = reinterpret_cast<char*>(&x);
typeid(*c);
is not UB, and will say char.

struct A { virtual ~A() {} };
A a;
char* c = reinterpret_cast<char*>(&a);
typeid(*c);
is not UB, and will say char.

struct A { virtual ~A() {} };
C c;
A* a = reinterpret_cast<A*>(&c);
typeid(*a);
is UB and may/will crash horribly.
--------------------------------------------------------------

Yes all this is known but we are diverting off the subject, this has nothing
to do with this non modifiable object of array type than Ian is suggesting
doesn't exist.
He may be correct in the case I put forward as I didn't create an non
modifiable object of array type. This is the debate , not what typeid does
or does not do.
 
J

Joel C. Salomon

The array type object , is an object that could be described as a non
modifiable pointer to the array of ints, with added typeinfo to support C++
references, sizeof and typeid.
Do you agree with this? If not what do you think is wrong about it?

What's wrong with saying that an array object is what it actually is,
*plus* it has the useful property that the operation &a[0] is
automatically applied wherever needed. E.g.,

int a[] = {1, 2, 3, 4};
int *p = a; // == `int *p = &a[0];`
a[2] = 7; // == `*(&a[0] + 2) = 7;`
2[a] = 7; // == `*(2 + &a[0]) = 7;`

(Or, what's wrong with saying an array object is "really" a gerbil,
but the compiler masks the distinction for you?)

--Joel
 
P

Paul

Ian Collins said:
Ian Collins said:
On 05/25/11 10:13 PM, Paul wrote:

On 05/25/11 08:11 AM, Paul wrote:
On 05/25/11 12:58 AM, Paul wrote:

You are not addressing the what stores the memory address.

Because there isn't an address to store. The typeid operator (like
sizeof) works with types, not values. In a simple case such as this
the
operand is not evaluated. Until you understand this you will be
stuck
in
limbo.

I could have simplified my simplification further by writing

std::cout<< typeid(int[3]).name()<< std::endl;

See? No memory address just a type.


There is an address stored.

Look at the code :

int main(){
int (*pp)[3] = (int (*)[3])new int[3];
std::cout<<*pp;
}
If this does not output an address what the hell is it?

The value returned by new.

Which is an address value.

Correct, an int*.

A memory address value is stored so there must be an object to
store
this
value, you say there is no object so what is it that stores this
value?

There isn't an address. Where's the address in typeid(int).name()?
Or
sizeof(int)?

The address is shown in my code above.

The address in your code id the value return by new. No amount of
casting
will change that.

The value returned from new is a pointer value that is an address.

Why do you think it is not an address?

I don't. You changed the context. You originally posted

std::cout<< typeid(*p2).name();

No I originally posted:
pparr p1 = (pparr)new int[3];
pparr p2= p1;
delete[] p1;
std::cout<< *p2<<std::endl;

You conveniently omitted the last line:

No I didn't conveniently onit anything. I was proving the fact that the code
I originally posted output an address.
std::cout<< typeid(*p2).name();


That is one possible outcome of UB. It could also have output garbage, or
if you have been using one of my specialised x86 debug allocators, aborted
the process.


It isn't passed an object. It gives us the *static* type of the expression
it is applied to. The exception is when the expression is polymorphic
class type.
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?
 
J

Joshua Maurice

"Joshua Maurice" <[email protected]> wrote in message
--No it could not be described like that. As has been demonstrated
--before, sizeof(arr) != sizeof(&arr[0]). What makes me think you're
--wrong? A careful reading of the standard, my education, and how all
--compilers are implemented.
I am not satisfied with your reply, I asked you, if you disagreed, to
explain what was wrong about it. You have not explained what you think is
wrong about it.

--I did. It's a definitional issue. You are using words contrary to
--their otherwise universally agreed upon definitions. There is no
--recourse in this argument besides argument from authority and argument
--from consensus, or similar arguments. You are simply wrong. An array
--is not simply an immutable pointer. An array object is a region of
--memory which contains some number of contiguous (ignoring padding) sub-
--objects. There is no magic hidden pointer like what you describe.

No we were talking about the non modifiable object of array type.
You are now talking about a sequence of modifiable objects. Again you revert
back to ignorance of the fact that this object of array type exists.
Forget the modifiable array, and think about the non modifiable object of
array type, what is that object in your own words?

The array object is not (directly) modifiable. This is a shorthand for
several things, such as an array object lvalue may not be on the left
hand side of a built-in assignment operator. However, the sub-objects
of the array object, aka the array elements, are modifiable. Obviously
the elements of an array are modifiable, but expressions of array type
are not modifiable.
 
I

Ian Collins

Ian Collins said:
It isn't passed an object. It gives us the *static* type of the expression
it is applied to. The exception is when the expression is polymorphic
class type.
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?

In the context of typeid, no. It is an expression (which has a type).
 
J

Joshua Maurice

On 05/26/11 09:39 AM, Paul wrote:
On 05/25/11 10:13 PM, Paul wrote:
On 05/25/11 08:11 AM, Paul wrote:
On 05/25/11 12:58 AM, Paul wrote:
You are not addressing the what stores the memory address.
Because there isn't an address to store.  The typeid operator (like
sizeof) works with types, not values.  In a simple case such asthis
the
operand is not evaluated.  Until you understand this you will be
stuck
in
limbo.
I could have simplified my simplification further by writing
std::cout<<    typeid(int[3]).name()<<    std::endl;
See?  No memory address just a type.
There is an address stored.
Look at the code :
int main(){
    int (*pp)[3] = (int (*)[3])new int[3];
    std::cout<<*pp;
}
If this does not output an address what the hell is it?
The value returned by new.
Which is an address value.
Correct, an int*.
A memory address value is stored so there must be an object to
store
this
value, you say there is no object so what is it that stores this
value?
There isn't an address.  Where's the address in typeid(int).name()?
Or
sizeof(int)?
The address is shown in my code above.
The address in your code id the value return by new.  No amount of
casting
will change that.
The value returned from new is a pointer value that is an address.
Why do you think it is not an address?
I don't.  You changed the context.  You originally posted
std::cout<<   typeid(*p2).name();
No I originally posted:
  pparr p1 = (pparr)new int[3];
  pparr p2= p1;
  delete[] p1;
  std::cout<<   *p2<<std::endl;
You conveniently omitted the last line:

No I didn't conveniently onit anything. I was proving the fact that the code
I originally posted output an address.










 std::cout<< typeid(*p2).name();
That is one possible outcome of UB.  It could also have output garbage, or
if you have been using one of my specialised x86 debug allocators, aborted
the process.
It isn't passed an object. It gives us the *static* type of the expression
it is applied to.  The exception is when the expression is polymorphic
class type.

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.

typeid takes a variety of expressions. For expressions of static type,
it doesn't matter if its passed a null pointer dereference or a valid
lvalue or whatever - /except/ when it's passed an expression of
polymorphic static type. That is all Ian was saying. He was just
saying that typeid in that particular case doesn't look at the
underlying object. It just looks at the type. *p is still an
expression of object type.
 
V

Vidar Hasfjord

Ok in connection to my previous post, lets remove the null pointer issue and
consider this:

#include <iostream>

typedef int (*pparr)[3];

int main(){
pparr p1 = (pparr)new int[3];
pparr p2= p1;
delete[] p1;
std::cout<< *p2<<std::endl;
std::cout<< typeid(*p2).name();

}

Unfortunately, as others have remarked, even this latest attempt of
yours to discuss the finer points of arrays and pointers in C++ may
fail due to confusion about your terminology.

Also, to eliminate all the non-consequential quirks of the built-in
legacy array from the discussion, consider using the new regular
std::array to illustrate your points, e.g.:

typedef std::array <int, 3>* pa;

int main () {
pa p1 = new std::array <int, 3>;
pa p2 = p1;
delete p1;
std::cout << *p2 << std::endl; // UB!
std::cout << typeid (*p2).name ();
}

If an issue does not apply equally to std::array, it is merely legacy
baggage from C and nothing fundamental to the C++ type system.

Regards,
Vidar Hasfjord
 
P

Paul

The array type object , is an object that could be described as a non
modifiable pointer to the array of ints, with added typeinfo to support
C++
references, sizeof and typeid.
Do you agree with this? If not what do you think is wrong about it?

--What's wrong with saying that an array object is what it actually is,
--*plus* it has the useful property that the operation &a[0] is
--automatically applied wherever needed. E.g.,

Well I have been saying that it is an array type object but nobody accepts
that an array type objects exists. As it is written in the standard as a non
modifiable object of array type , perhaps my terminology is not 100% the
same as the standards but I see no idfference in the two terms
1) array type object
2) object of array type.


-- int a[] = {1, 2, 3, 4};
-- int *p = a; // == `int *p = &a[0];`
-- a[2] = 7; // == `*(&a[0] + 2) = 7;`

Your code :
*(&a[0] + 2)
does this
*((&(*(a+0))) +2)
which is not the same as this
*(a+2)
which is what a[2] is interpreted as.

It gives the same result but there is more work for the compiler.
 
P

Paul

"Joshua Maurice" <[email protected]> wrote in message
--No it could not be described like that. As has been demonstrated
--before, sizeof(arr) != sizeof(&arr[0]). What makes me think you're
--wrong? A careful reading of the standard, my education, and how all
--compilers are implemented.
I am not satisfied with your reply, I asked you, if you disagreed, to
explain what was wrong about it. You have not explained what you think
is
wrong about it.

--I did. It's a definitional issue. You are using words contrary to
--their otherwise universally agreed upon definitions. There is no
--recourse in this argument besides argument from authority and argument
--from consensus, or similar arguments. You are simply wrong. An array
--is not simply an immutable pointer. An array object is a region of
--memory which contains some number of contiguous (ignoring padding) sub-
--objects. There is no magic hidden pointer like what you describe.

No we were talking about the non modifiable object of array type.
You are now talking about a sequence of modifiable objects. Again you
revert
back to ignorance of the fact that this object of array type exists.
Forget the modifiable array, and think about the non modifiable object of
array type, what is that object in your own words?

--The array object is not (directly) modifiable. This is a shorthand for
--several things, such as an array object lvalue may not be on the left
--hand side of a built-in assignment operator.

I don't know what you are trying to say here AFAIK an object of array type
is not modifiable at all.

-- However, the sub-objects
--of the array object, aka the array elements, are modifiable.
--Obviously
--the elements of an array are modifiable, but expressions of array type
--are not modifiable.

What do you mean by expressions of array type are not modifiable?
Are any expressions modifiable outwith the realms of changing the text in a
text editor?
Do you mean objects of array types are not modifiable?
 
P

Paul

Ian Collins said:
Ian Collins said:
It isn't passed an object. It gives us the *static* type of the
expression
it is applied to. The exception is when the expression is polymorphic
class type.
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?

In the context of typeid, no. It is an expression (which has a type).
This is not the question, It doesn't matter what typeid thinks of it.
DOes p2 point to an object of array type?
 
P

Paul

Vidar Hasfjord said:
Ok in connection to my previous post, lets remove the null pointer issue
and
consider this:

#include <iostream>

typedef int (*pparr)[3];

int main(){
pparr p1 = (pparr)new int[3];
pparr p2= p1;
delete[] p1;
std::cout<< *p2<<std::endl;
std::cout<< typeid(*p2).name();

}

Unfortunately, as others have remarked, even this latest attempt of
yours to discuss the finer points of arrays and pointers in C++ may
fail due to confusion about your terminology.
What terminology confuses you?
Also, to eliminate all the non-consequential quirks of the built-in
legacy array from the discussion, consider using the new regular
std::array to illustrate your points, e.g.:

typedef std::array <int, 3>* pa;

int main () {
pa p1 = new std::array <int, 3>;
pa p2 = p1;
delete p1;
std::cout << *p2 << std::endl; // UB!
std::cout << typeid (*p2).name ();
}

If an issue does not apply equally to std::array, it is merely legacy
baggage from C and nothing fundamental to the C++ type system.
My C++ compiler does not support this.
 
J

Joshua Maurice

--What's wrong with saying that an array object is what it actually is,
--*plus* it has the useful property that the operation &a[0] is
--automatically applied wherever needed.  E.g.,

Well I have been saying that it is an array type object but nobody accepts
that an array type objects exists. As it is written in the standard as a non
modifiable object of array type , perhaps my terminology is not 100% the
same as the standards but I see no idfference in the two terms
1) array type object
2) object of array type.

I now see what you're saying. You are simply wrong.
void f()
{
int x[3];
}
That allocates a piece of memory on the stack. (At least for all
common implementations which happen to use stack.) That region of
memory, which contains 3 contiguous int sub-objects (barring padding),
is a single object. That is the array object. The array object
contains the 3 int sub-objects. The array object is not some object
distinct from the 3 int objects. The array object and the 3 int
objects occupy the same region of memory. The 3 int objects are sub-
objects of the array object. It behaves very similar to:
struct x_t { operator int* (); private: int x0; int x1; int x2; }
x_t x;

Array objects are not modifiable. That was not intended to mean that
the memory of the object cannot change. It was a shorthand for several
facts about the type system, including expressions of array type may
not appear on the left hand side of built-in assignment operators.

The memory of the array object may change, but only through
expressions of the element type, not the array type. (Or char or
unsigned char, or memcpy, etc.)
--    int a[] = {1, 2, 3, 4};
--    int *p = a; // == `int *p = &a[0];`
--    a[2] = 7;   // == `*(&a[0] + 2) = 7;`

Your code :
*(&a[0] + 2)
does this
*((&(*(a+0))) +2)
which is not the same as this
*(a+2)
which is what a[2] is interpreted as.

It gives the same result but there is more work for the compiler.

That's a mighty curious definition of "the same". On any half-way
decent compiler, with even a modicum of optimization turned on, I
would expect that both code pieces will result in the same assembly.
That is what any reasonable person understood the term "the same" to
mean in context. Stop trolling, and stop being contrarian for no good
reason.
 
P

Paul

You are not addressing the what stores the memory address.
Because there isn't an address to store. The typeid operator (like
sizeof) works with types, not values. In a simple case such as
this
the
operand is not evaluated. Until you understand this you will be
stuck
in
limbo.
I could have simplified my simplification further by writing
std::cout<< typeid(int[3]).name()<< std::endl;
See? No memory address just a type.
There is an address stored.
Look at the code :
int main(){
int (*pp)[3] = (int (*)[3])new int[3];
std::cout<<*pp;
}
If this does not output an address what the hell is it?
The value returned by new.
Which is an address value.
Correct, an int*.
A memory address value is stored so there must be an object to
store
this
value, you say there is no object so what is it that stores this
value?
There isn't an address. Where's the address in typeid(int).name()?
Or
sizeof(int)?
The address is shown in my code above.
The address in your code id the value return by new. No amount of
casting
will change that.
The value returned from new is a pointer value that is an address.
Why do you think it is not an address?
I don't. You changed the context. You originally posted
std::cout<< typeid(*p2).name();
No I originally posted:
pparr p1 = (pparr)new int[3];
pparr p2= p1;
delete[] p1;
std::cout<< *p2<<std::endl;
You conveniently omitted the last line:

No I didn't conveniently onit anything. I was proving the fact that the
code
I originally posted output an address.


std::cout<< typeid(*p2).name();
That is one possible outcome of UB. It could also have output garbage,
or
if you have been using one of my specialised x86 debug allocators,
aborted
the process.
It isn't passed an object. It gives us the *static* type of the
expression
it is applied to. The exception is when the expression is polymorphic
class type.

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 ?
 
V

Vidar Hasfjord

[...]
The array type object , is an object that could be described as a non
modifiable pointer to the array of ints, with added typeinfo to support C++
references, sizeof and typeid.
Do you agree with this? If not what do you think is wrong about it?

Well, it sound more like the array concept of C's predecessor B, in
which an array in fact where a reference type, always represented in
the machine code as a pointer to the array elements allocated in
static memory. While designing C, Dennis Ritchie had to make an array
into a proper value type to be able to aggregate arrays in structures
like any other types. But to stay compatible with B and early C (aka
NB) code he devised the odd array-to-pointer decay and conversion
rules that has survived in C++ to this day.

Read the whole story here:
http://cm.bell-labs.com/cm/cs/who/dmr/chist.html
 
J

Joshua Maurice

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.

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]".

First. You're not guaranteed that a "int(*)[3]" has enough precision
to store a int*. You may lose precision. It may be "rounded".

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.
 
P

Paul

message--What's wrong with saying that an array object is what it actually is,
--*plus* it has the useful property that the operation &a[0] is
--automatically applied wherever needed. E.g.,

Well I have been saying that it is an array type object but nobody accepts
that an array type objects exists. As it is written in the standard as a
non
modifiable object of array type , perhaps my terminology is not 100% the
same as the standards but I see no idfference in the two terms
1) array type object
2) object of array type.

--I now see what you're saying. You are simply wrong.
About what exactly?
-- void f()
-- {
-- int x[3];
-- }
--That allocates a piece of memory on the stack. (At least for all
--common implementations which happen to use stack.) That region of
--memory, which contains 3 contiguous int sub-objects (barring padding),
--is a single object. That is the array object. The array object
--contains the 3 int sub-objects. The array object is not some object
--distinct from the 3 int objects. The array object and the 3 int
--objects occupy the same region of memory. The 3 int objects are sub-
--objects of the array object. It behaves very similar to:
-- struct x_t { operator int* (); private: int x0; int x1; int x2; }
-- x_t x;

You have not described a non modifiable object, you have described 3 integer
objects that are modifiable.
This object you have described can be modified bit by bit , there is no way
this object can be said to be a non modifiable array type object.

The only non modifable object here is the object represented by the
identifier arr. This object holds a vlaue that is a memory address and this
value is not stored with the array of three integers. That means this object
is an object in its own right that takes up memory over and above the memory
used for the 3 integer objects.



--Array objects are not modifiable. That was not intended to mean that
--the memory of the object cannot change. It was a shorthand for several
--facts about the type system, including expressions of array type may
--not appear on the left hand side of built-in assignment operators.

What is means is that the value of an array type object cannot change , that
value is the address of the initial element of the array.


--The memory of the array object may change, but only through
--expressions of the element type, not the array type. (Or char or
--unsigned char, or memcpy, etc.)

What do you mean by the memory of the array object?
Do you mean the memory that holds the address of the first element , or the
memory that holds the values stroed in the elements?
 
P

Paul

[...]
The array type object , is an object that could be described as a non
modifiable pointer to the array of ints, with added typeinfo to support
C++
references, sizeof and typeid.
Do you agree with this? If not what do you think is wrong about it?

Well, it sound more like the array concept of C's predecessor B, in
which an array in fact where a reference type, always represented in
the machine code as a pointer to the array elements allocated in
static memory. While designing C, Dennis Ritchie had to make an array
into a proper value type to be able to aggregate arrays in structures
like any other types. But to stay compatible with B and early C (aka
NB) code he devised the odd array-to-pointer decay and conversion
rules that has survived in C++ to this day.

Read the whole story here:
http://cm.bell-labs.com/cm/cs/who/dmr/chist.html
 
J

Joshua Maurice

--  void f()
--  {
--    int x[3];
--  }
--That allocates a piece of memory on the stack. (At least for all
--common implementations which happen to use stack.) That region of
--memory, which contains 3 contiguous int sub-objects (barring padding),
--is a single object. That is the array object. The array object
--contains the 3 int sub-objects. The array object is not some object
--distinct from the 3 int objects. The array object and the 3 int
--objects occupy the same region of memory. The 3 int objects are sub-
--objects of the array object. It behaves very similar to:
 -- struct x_t { operator int* (); private: int x0; int x1; int x2; }
 -- x_t x;

You have not described a non modifiable object, you have described 3 integer
objects that are modifiable.
This object you have described can be modified bit by bit , there is no way
this object can be said to be a non modifiable array type object.

The only non modifable object here is the object represented by the
identifier arr. This object holds a vlaue that is a memory address and this
value is not stored with the array of three integers. That means this object
is an object in its own right that takes up memory over and above the memory
used for the 3 integer objects.

--Array objects are not modifiable. That was not intended to mean that
--the memory of the object cannot change. It was a shorthand for several
--facts about the type system, including expressions of array type may
--not appear on the left hand side of built-in assignment operators.

What is means is that the value of an array type object cannot change , that
value is the address of the initial element of the array.

And you are wrong. You are wrong by definition, and your views lead to
demonstrably wrong conclusions. One such demonstration is the program
I have else-thread that shows that "int(*)[3]" points to a region of
memory of 3 contiguous int objects. There is no hidden unmodifiable
pointer that points to the first element. It is a figment of your
imagination.
 
P

Paul

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.


--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?
 
J

Joshua Maurice

"Joshua Maurice" <[email protected]> wrote in message
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.

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
--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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top