Lets put it another way

P

Paul

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();
}


In the last 2 lines does an array type object exist, even though there is no
array object?

If not what is the object that stores the address and is interpreted as an
array type by the typeid expression?
 
I

Ian Collins

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;

UB yet again.
std::cout<< typeid(*p2).name();
}


In the last 2 lines does an array type object exist, even though there is no
array object?
No.

If not what is the object that stores the address and is interpreted as an
array type by the typeid expression?

The typeid and sizeof operators do not evaluate their expression (unless
in case of typeid the type is polymorphic). So no object is required.
 
J

Joshua Maurice

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;

UB yet again.

Actually, he has UB even earlier. He has UB at the delete[]. The type
of the expression "new int[3]" is "int*". The type of the expression
passed to delete[] to free that object must be the same type, "int*".
It's not, and thus UB.
 
P

Paul

Ian Collins 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;

UB yet again.
std::cout<< typeid(*p2).name();
}


In the last 2 lines does an array type object exist, even though there is
no
array object?
No.

If not what is the object that stores the address and is interpreted as
an
array type by the typeid expression?

The typeid and sizeof operators do not evaluate their expression (unless
in case of typeid the type is polymorphic). So no object is required.
You do not seem to understand the question.
I said ..if not what is the object that stores the address?
So what is this object? Do you know?
 
P

Paul

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;

UB yet again.

--Actually, he has UB even earlier. He has UB at the delete[]. The type
--of the expression "new int[3]" is "int*". The type of the expression
--passed to delete[] to free that object must be the same type, "int*".
--It's not, and thus UB.

I raised this question about delete or delete[] on 28/03/2011 and you didn't
know the answer then.
The objects that need to be deleted are integer objects. and they get
deleted in this case.
If you think it is necessary to cast to int* prior to calling delete then
assume that and then can you answer the question about the object that
contains the memory address, or do you not know?
 
J

Joshua Maurice

On 05/24/11 01:14 PM, Paul wrote:
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;
UB yet again.

--Actually, he has UB even earlier. He has UB at the delete[]. The type
--of the expression "new int[3]" is "int*". The type of the expression
--passed to delete[] to free that object must be the same type, "int*".
--It's not, and thus UB.

I raised this question about delete or delete[] on 28/03/2011 and you didn't
know the answer then.

I'm pretty sure I knew, and I suspect that you're willfully lying.
The objects that need to be deleted are integer objects. and they get
deleted in this case.

No. An array object is the thing that was allocated, and it is an
array object that needs to be passed to delete[].
If you think it is necessary to cast to int* prior to calling delete then
assume that

It's not what I think. It's what the standard says.
and then can you answer the question about the object that
contains the memory address, or do you not know?

Your original question in the OP post about "array type objects" vs
"array objects" makes no sense because you invented the terms, and no
one else knows what they mean.

#include<iostream>
typedef int (*pparr)[3];
int main(){
pparr p1 = (pparr)new int[3];
pparr p2= p1;
delete[] p1;
std::cout<< *p2<<std::endl;
}

This program
1- dynamically allocates an array object, specifically "int [3]",
2- does some funky incorrect casting invoking platform specific
behavior (we're not guaranteed that a "int (*)[3]" pointer can round-
trip store a "int *" pointer),
3- calls delete[] on a pointer of the wrong type and thus invokes UB,
4- and finally, the program again invokes UB by attempting to read the
result of a null pointer dereference.
 
J

Joshua Maurice

4- and finally, the program again invokes UB by attempting to read the
result of a null pointer dereference.

Err, sorry, not null pointer dereference. My apologies. It's an
indeterminate value. This is clearer in the C standard where they
cleared this up recently AFAIK. As soon as a pointer to a dynamically
allocated piece of memory has been passed to a deallocation function,
all copies of that pointer value, and moreover all pointer values in
the entire program that point into that region of memory, become
indeterminant. Any read of an indeterminant value is UB.
 
I

Ian Collins

Ian Collins 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;

UB yet again.
std::cout<< typeid(*p2).name();
}


In the last 2 lines does an array type object exist, even though there is
no
array object?
No.

If not what is the object that stores the address and is interpreted as
an
array type by the typeid expression?

The typeid and sizeof operators do not evaluate their expression (unless
in case of typeid the type is polymorphic). So no object is required.
You do not seem to understand the question.

You do not appear to understand the answer.
I said ..if not what is the object that stores the address?
So what is this object? Do you know?

There isn't an object. The compiler knows the type of *p2. You may as
well have written

#include <iostream>
#include <typeinfo>

typedef int (*pparr)[3];

int main(){
pparr p2;
std::cout << typeid(*p2).name() << std::endl;
}
 
P

Paul

Ian Collins said:
Ian Collins said:
On 05/24/11 01:14 PM, Paul wrote:
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;

UB yet again.

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


In the last 2 lines does an array type object exist, even though there
is
no
array object?

No.

If not what is the object that stores the address and is interpreted as
an
array type by the typeid expression?

The typeid and sizeof operators do not evaluate their expression (unless
in case of typeid the type is polymorphic). So no object is required.
You do not seem to understand the question.

You do not appear to understand the answer.
I said ..if not what is the object that stores the address?
So what is this object? Do you know?

There isn't an object. The compiler knows the type of *p2. You may as
well have written

#include <iostream>
#include <typeinfo>

typedef int (*pparr)[3];

int main(){
pparr p2;
std::cout << typeid(*p2).name() << std::endl;
}
You are not addressing the what stores the memory address.
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?
 
P

Paul

On 05/24/11 01:14 PM, Paul wrote:
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;
UB yet again.

--Actually, he has UB even earlier. He has UB at the delete[]. The type
--of the expression "new int[3]" is "int*". The type of the expression
--passed to delete[] to free that object must be the same type, "int*".
--It's not, and thus UB.

I raised this question about delete or delete[] on 28/03/2011 and you
didn't
know the answer then.

--I'm pretty sure I knew, and I suspect that you're willfully lying.

No I'm not lying. In response to my question about how to delete such an
object you wrote:

"I'd like to point out that AFAIK the first cast may result in a loss
of information. You're only guaranteed round-way trips through void*,
char*, and unsigned char*, (and an integer type of sufficient size).
Thus the delete[] could be UB on a conforming platform. That's right,
right?"

Ref: Posting on "delete or delete[]" on 28/3/2011


The objects that need to be deleted are integer objects. and they get
deleted in this case.

--No. An array object is the thing that was allocated, and it is an
--array object that needs to be passed to delete[].

No three integer objects were allocated and three integers must be
deallocated.
It is not one object that is allocated is it three, as this code shows:

#include <iostream>

class Foo{
public:
Foo(){std::cout<<"Constructing Foo\n";}
~Foo(){std::cout<<"Destructing Foo\n";}
};

typedef Foo (*arr_ptr)[3];

int main(){
arr_ptr foop = (arr_ptr)new Foo[3];
delete[] (Foo*)foop; /*cast back to keep you happy :)*/
}

If you think it is necessary to cast to int* prior to calling delete then
assume that

--It's not what I think. It's what the standard says.

The deletion of the dynamically allocated array was not really relevant but
if you must argue about this then cast it back as I did in my code above.
and then can you answer the question about the object that
contains the memory address, or do you not know?

--Your original question in the OP post about "array type objects" vs
--"array objects" makes no sense because you invented the terms, and no
--one else knows what they mean.

My question is about the object that stores the memory address we get when
we dereference p2.


--#include<iostream>
--typedef int (*pparr)[3];
--int main(){
-- pparr p1 = (pparr)new int[3];
-- pparr p2= p1;
-- delete[] p1;
-- std::cout<< *p2<<std::endl;
--}

--This program
--1- dynamically allocates an array object, specifically "int [3]",

I don't see it as allocating one single object , I see it as allocating and
array of 3 int objects.


--2- does some funky incorrect casting invoking platform specific
--behavior (we're not guaranteed that a "int (*)[3]" pointer can round-
--trip store a "int *" pointer),

In what way is this pointer casting incorrect?
I would be very surprised if this cast was incorrect as it is a usefull way
of converting a dynamic array into a reference type, for example:

class Foo{
public:
Foo(){std::cout<<"Constructing Foo\n";}
~Foo(){std::cout<<"Destructing Foo\n";}
int x;
};

void Bar( Foo (&arg)[3]){
std::cout<<"In Bar\n";
arg[0].x= 1;
arg[1].x= 2;
arg[2].x= 3;
}

typedef Foo (*arr_ptr)[3];

int main(){
arr_ptr foop = (arr_ptr)new Foo[3];
Bar(*foop);
std::cout<< (*foop)[2].x;
}



--3- calls delete[] on a pointer of the wrong type and thus invokes UB,

That is easily corrected by casting back , this is not a point important to
the question.

--4- and finally, the program again invokes UB by attempting to read the
--result of a null pointer dereference.

There is no null pointers here.
 
P

Paul

4- and finally, the program again invokes UB by attempting to read the
result of a null pointer dereference.

--Err, sorry, not null pointer dereference. My apologies. It's an
--indeterminate value. This is clearer in the C standard where they
--cleared this up recently AFAIK. As soon as a pointer to a dynamically
--allocated piece of memory has been passed to a deallocation function,
--all copies of that pointer value, and moreover all pointer values in
--the entire program that point into that region of memory, become
--indeterminant. Any read of an indeterminant value is UB.


*p2 does not attempt to access the deallocated memory.
*p2 yields a memory address, it accesses some object that seems to be a
pointer in most situations, but when passed to typeid or sizeof it does not
behave like a pointer.
This AFAICT from reading online seems to be the typical behaviour of a C++
array type object, therefore it seems that the pointer points to an array
type object which is created by the creation of the pointer itself and not
by the allocation.

For example consider this simple example:
int* p = new int[16];

In this dynamic array there is no array type object. It is a simple int*
that points to a block of memory.
sizeof and typeid do not work here because there is no array object.
Now consider this:

int (*p)[3] = (int (*)[3])new int[3];
Now we have an arraytype object because we can access typeinfo and sizeof.

The allocation of memory alone does not create an array type object, it is
the declaration of an object using square brackets that creates the array
type object.
 
I

Ian Collins

Ian Collins said:
On 05/24/11 01:14 PM, Paul wrote:
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;

UB yet again.

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


In the last 2 lines does an array type object exist, even though there
is
no
array object?

No.

If not what is the object that stores the address and is interpreted as
an
array type by the typeid expression?

The typeid and sizeof operators do not evaluate their expression (unless
in case of typeid the type is polymorphic). So no object is required.

You do not seem to understand the question.

You do not appear to understand the answer.
I said ..if not what is the object that stores the address?
So what is this object? Do you know?

There isn't an object. The compiler knows the type of *p2. You may as
well have written

#include<iostream>
#include<typeinfo>

typedef int (*pparr)[3];

int main(){
pparr p2;
std::cout<< typeid(*p2).name()<< std::endl;
}
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.
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)?
 
P

Paul

Ian Collins 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;

UB yet again.

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


In the last 2 lines does an array type object exist, even though
there
is
no
array object?

No.

If not what is the object that stores the address and is interpreted
as
an
array type by the typeid expression?

The typeid and sizeof operators do not evaluate their expression
(unless
in case of typeid the type is polymorphic). So no object is required.

You do not seem to understand the question.

You do not appear to understand the answer.

I said ..if not what is the object that stores the address?
So what is this object? Do you know?

There isn't an object. The compiler knows the type of *p2. You may as
well have written

#include<iostream>
#include<typeinfo>

typedef int (*pparr)[3];

int main(){
pparr p2;
std::cout<< typeid(*p2).name()<< std::endl;
}
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?

There isn't an address. Where's the address in typeid(int).name()? Or
sizeof(int)?
The address is shown in my code above.
Have you lost your brain today?
 
J

Joshua Maurice

--Err, sorry, not null pointer dereference. My apologies. It's an
--indeterminate value. This is clearer in the C standard where they
--cleared this up recently AFAIK. As soon as a pointer to a dynamically
--allocated piece of memory has been passed to a deallocation function,
--all copies of that pointer value, and moreover all pointer values in
--the entire program that point into that region of memory, become
--indeterminant. Any read of an indeterminant value is UB.

*p2 does not attempt to access the deallocated memory.

Doesn't matter. It's UB. Attempting to read the pointer, not the
deallocated memory, is UB. At least it is according to the C spec, and
I expect that the C++ standard will follow suit if it hasn't already.
For example consider this simple example:
int* p = new int[16];

In this dynamic array there is no array type object. It is a simple int*
that points to a block of memory.
sizeof and typeid do not work here because there is no array object.
Now consider this:

int (*p)[3] = (int (*)[3])new int[3];
Now we have an arraytype object because we can access typeinfo and sizeof..

The allocation of memory alone does not create an array type object, it is
the declaration of an object using square brackets that creates the array
type object.

And I still don't know what you mean by array type object vs array
object. Until you explain that technical distinction to me, you're
literally just spouting effective nonsense, as you just invented those
terms and no one else knows what you're saying.
 
J

Joshua Maurice

--3- calls delete[] on a pointer of the wrong type and thus invokes UB,

That is easily corrected by casting back , this is not a point important to
the question.

Any dereference of that pointer, basically, is UB. There's no reason
to do the cast in the first place.
 
P

Paul

--Err, sorry, not null pointer dereference. My apologies. It's an
--indeterminate value. This is clearer in the C standard where they
--cleared this up recently AFAIK. As soon as a pointer to a dynamically
--allocated piece of memory has been passed to a deallocation function,
--all copies of that pointer value, and moreover all pointer values in
--the entire program that point into that region of memory, become
--indeterminant. Any read of an indeterminant value is UB.

*p2 does not attempt to access the deallocated memory.

--Doesn't matter. It's UB. Attempting to read the pointer, not the
--deallocated memory, is UB. At least it is according to the C spec, and
--I expect that the C++ standard will follow suit if it hasn't already

This pointer obviously points to something that has a value that is
displayed on the screen as a memory address. It certainly doesn't point to
the integer objects that were allocated by new, so what does it point to?
How can you say it is UB if you do not first establish what it is pointing
to?
For example consider this simple example:
int* p = new int[16];

In this dynamic array there is no array type object. It is a simple int*
that points to a block of memory.
sizeof and typeid do not work here because there is no array object.
Now consider this:

int (*p)[3] = (int (*)[3])new int[3];
Now we have an arraytype object because we can access typeinfo and sizeof.

The allocation of memory alone does not create an array type object, it is
the declaration of an object using square brackets that creates the array
type object.

--And I still don't know what you mean by array type object vs array
--object. Until you explain that technical distinction to me, you're
--literally just spouting effective nonsense, as you just invented those
--terms and no one else knows what you're saying.

Well consider the following:

int arr[3]={0};
std::cout<< arr;

The above does not output an array object, it outputs a memory address.
To output the array object you need to loop and dereference:

for (int i=0; i<3; ++i){
std::cout<< arr << std::endl;
}

The array type object is a region of memory that contains a value that is
some memory address.
The array object is a region of memory than contains three integer objects,
each with the value 0.
 
P

Paul

--3- calls delete[] on a pointer of the wrong type and thus invokes UB,

That is easily corrected by casting back , this is not a point important
to
the question.

--Any dereference of that pointer, basically, is UB. There's no reason
--to do the cast in the first place.

What derefernecing any pointer in C++ is UB?
Or just pointers to array type objects?

I'm unsure what you are saying here, what do you think this pointer points
to?
 
O

Oliver Jackson

On 05/25/11 12:58 AM, Paul wrote:
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;
UB yet again.
    std::cout<<    typeid(*p2).name();
}
In the last 2 lines does an array type object exist, even though
there
is
no
array object?
No.
If not what is the object that stores the address and is interpreted
as
an
array type by the typeid expression?
The typeid and sizeof operators do not evaluate their expression
(unless
in case of typeid the type is polymorphic).  So no object is required.
You do not seem to understand the question.
You do not appear to understand the answer.
I said ..if not what is the object that stores the address?
So what is this object? Do you know?
There isn't an object.  The compiler knows the type of *p2.  You may as
well have written
#include<iostream>
#include<typeinfo>
typedef int (*pparr)[3];
int main(){
   pparr p2;
   std::cout<<  typeid(*p2).name()<<  std::endl;
}
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?
There isn't an address.  Where's the address in typeid(int).name()?  Or
sizeof(int)?

The address is shown in my code above.
Have you lost your brain today?

**** yeah! Your posts ROCK!!
 
J

Joshua Maurice

--Doesn't matter. It's UB. Attempting to read the pointer, not the
--deallocated memory, is UB. At least it is according to the C spec, and
--I expect that the C++ standard will follow suit if it hasn't already

This pointer obviously points to something that has a value that is
displayed on the screen as a memory address. It certainly doesn't point to
the integer objects that were allocated by new, so what does it point to?
How can you say it is UB if you do not first establish what it is pointing
to?

Take the following program:
#include <stdlib.h>
#include <stdio.h>
int main()
{ char* a = (char*)malloc(1);
char* b = a;
free(a);
printf("%p\n", b);
}
This program has UB in C, and as I said will likely have UB in C++, or
it already is UB in C++. See the defect report for more details:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_260.htm
--And I still don't know what you mean by array type object vs array
--object. Until you explain that technical distinction to me, you're
--literally just spouting effective nonsense, as you just invented those
--terms and no one else knows what you're saying.

Well consider the following:

int arr[3]={0};
std::cout<< arr;

The above does not output an array object, it outputs a memory address.
To output the array object you need to loop and dereference:

for (int i=0; i<3; ++i){
std::cout<< arr << std::endl;

}

The array type object is a region of memory that contains a value that is
some memory address.
The array object is a region of memory than contains three integer objects,
each with the value 0.


I suggest you take a course in compilers, or read a book, like one of
the Dragon Books, Red or Green. You have gross misunderstandings of
both the C++ object model, and how compilers actually generate code.
There is no such thing as an "array-type object", as you've defined
it. In these examples, there are only array objects and pointer
objects - including pointers to arrays and pointers to individual
elements, not "array-type objects".

Consider:
void foo()
{ int x[3];
int* y = x;
cout << y;
}

"x" is a piece of text. It is a preprocessor token. It is an
identifier for an auto (stack) variable. It names an object. It names
an (array) object of type "int [3]". That array object has three sub-
objects of type "int".

"y" is a piece of text. It is a preprocessor token. It is an
identifier for an auto (stack) variable. It names an object. It names
a (pointer) object of type "int*". It holds the address of the first
element of the auto (stack) array x.

This function "uses" the following objects:
- the array object x, and its 3 unnamed int sub-objects,
- the pointer object y,
- the object cout.
There is no "array-type object".

There is no such thing as the array-type object. A common compiler
(and one which has sizeof(int) == 4) will implement this function by:
- allocating the stack space,
- taking the stack pointer and adding 0 to get the address of the
first element of the array object x,
- taking the stack pointer and adding 12 to get the address of the
pointer object y,
- storing the address of the first element of the array object x into
the object y, (we previously obtained both addressed - see above), (or
it'll put it into a register, or both, depending on the particulars
and how the compiler wants to use registers),
- set up the state required to call "std::eek:perator<<" according to the
calling-convention, which includes putting the value of the pointer
object y in memory a certain offset from the stack pointer register
value, or in a particular register,
- calling a jump instruction or some such to call function
"std::eek:perator<<",
- reading the return value of that function from a calling-convention
location, such as a particular register or from memory at a particular
offset from the stack pointer register value,
- and so on.

Consider the function:
void foo()
{ int* x = new int[3];
cout << x;
}

"x" is a piece of text. It is a preprocessor token. It is an
identifier for an auto (stack) variable. It names an object. It names
a (pointer) object of type "int*". It holds a value of the address of
the first element of the unnamed dynamically allocated array.

This function "uses" the following objects:
- the pointer object x,
- the object cout,
- the unnamed, dynamically allocated, array object.
- the 3 unnamed int sub-objects of the unnamed, dynamically allocated,
array object.
There is no "array-type object".

A common compiler will implement this function by:
- allocating the stack space,
- taking the stack pointer and adding 0 to get the address of the
pointer object x,
- set up the state required to call the new operator according to the
calling-convention, which includes putting the value 3 in memory a
certain offset from the stack pointer register value, or in a
particular register,
- reading the return value of that function from a calling-convention
location, such as a particular register or from memory at a particular
offset from the stack pointer register value,
- storing the return result of the function call, aka "new int[3]",
aka a pointer to the first element of the dynamically allocated array,
into the pointer object x, (we previously obtained its addressed - see
above), (or it'll put it into a register, or both, depending on the
particulars and how the compiler wants to use registers),
- and then it will call "std::eek:perator<<" just like it in the earlier
example,
- and so on.
 
I

Ian Collins

Ian Collins said:
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.
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.
Have you lost your brain today?

Oh how mature you are.
 

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
474,141
Messages
2,570,817
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top