Problem with array objects

P

Paul

Leigh Johnston said:
[snip]

It is an integer constant representing an offset to be applied
to a
stack frame pointer; it is NOT a pointer for any definition of
"pointer"; it is like saying 'foo' below is a C++ pointer
because we
add it to a C++ pointer:

const std::size_t foo = 42;
int *p = ...;
int *p2 = p + foo; // is foo a pointer? don't be stupid.

No incorrect , you said it was not a pointer in assembly
language.
Ovbioustly its not a C++ pointer, its an array type object.

Do you not understand the meaning of the words "it is like"? Do
you
know what an "analogy" is? Have you ever bothered to try "lateral
thinking"?

I never said it was a C++ pointer; I was giving you a C++
analogy of
why a pointer offset (for any definition of "pointer") is not a
pointer.

But a pointer in assembly is not the same as a pointer in C++. A
pointer
in C++ is a pointer type object, or an object of pointer type.
Assembly does not have types, a pointer in assembly is the same
as any
other variable or constant, except that its intended use is to
store an
address(or an offset) to another memory location.

I gave you an analogy; you obviously do not understand analogies. An
analogy explains one thing by comparing it to something else and
these
two things are *similar* in some respect not the *same*.

You cannot compare an elephants ability to lift objects with its
trunk
to that of an ant, because an ant doesn't have a trunk.
Likewise you cannot compare a C++ type, to an assembler variable or
constant because assembler doesn't have types.

You still do not understand what an analogy is. Fail.


Get a clue.

A pointer in assembly is anything that is being used to store an
address and a constant being used as a stack frame pointer offset is
not something which is being used to store an address; such a
constant
is only being used to emit machine code in the text segment.

No you are wrong a pointer is assembly does not necessarily store a
real
address, a variable that stores an offset or an index is also
considered
a pointer in assembly language.

No it isn't; see Ian Collins' reply which agrees with what I have been
saying with much clarity.

I refer you to section 5.5 Pointer data types in the following link:
http://www.oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter_5/CH05-1.html#HEADING1-197



Again you are confusing two different terms with the same name: an
Intel x86 segment offset is not the same as an offset used in
conjunction with a pointer (or address).

I never even mentioned segment offsets. You are the one who seems
confused.

The link you posted talks about x86 segment offsets so obviously one
can only conclude that that is what you are referring to when you
erroneously say an offset can be a pointer. Get a f**king clue. In x86
a segment offset can be considered a pointer as it forms part of a
logical address but we are not talking about segment offsets; we are
talking about offsets applied to already formed logical addresses.
No the example uses segment offset addressing as an example. You are
confusing the term "offset" with this seg::eek:ffset addressing syntax.

You are the one posting spurious links to irrelevent details of x86
assembly language programming; you are the one trying to force equivalence
between the different terms "offset" and "pointer".
Its not a spurious link , it is a link that gives a general definition of a
pointer in assembly language.
No; an "offset" is added to an address to create another address.

An address is an integer.

So why post a link which implies that that was *your* interpretation?
The link didn't imply my interpretation of anything. It's a link that gives
a general definiton of a pointer in assembly.
..
You are the one bringing irrelevances into what you laughingly call a
"debate".


A label being the name of a constant used as an offset applied to the
stack frame pointer IS NOT A POINTER; it is an offset; an offset *applied*
to a pointer.

Yes it is.
A pointer is something that points to another location.
_arr$ has the value -12 , so it points -12 bytes into the stack frame.

ebp is the stack base pointer and it's a hardware register that stores the
addrress of the stack frame. When _arr$ is added to ebp, _arr$ is being used
as a pointer, relative to the stack base.

Obviously you think a pointer is an object that resembles a C++ pointer and
must be a memory location that stores a memory address or soemthing, so you
disagree.

That's your opinion on what a pointer is an your welcome to it. I disagree
so stop spamming nonsense.

Get a f**king clue.

And abuse.
One can simulate a pointer to an array element using array indices
(offsets) but this is a purely a simulation; it is not a true pointer.
A pointer is something that points to a location, whether it's relative or
direct.
You can go simulate something that points to something if you like.
GL.
 
P

Paul

Thomas David Rivers said:
Oh - OK - let me see if I understand.

I did take the liberty of removing the previous words, just to shorten
the posting - I hope that is OK.

Ok np.
When I read it, I believe you were saying that in the declartion:

int arr[5];

that 'arr' was the _name_ of the array of 5 `int' elements.
Is that correct?

If you completely agree with that, I think we can proceed from
there.

Yes this is what we agreed on IIRC.
I did see some confusion regarding "compile-time" and "runtime",
which probably motivates definitions of those.

I would like to offer these definitions:

"compile-time" refers to the evaluation of the program's expression
during the compilation process. The compiler can, at its discretion,
evaluate an expression using information it can glean thru the
compilation process, or it can generate code that, when executed,
causes the execution platform to evaluate the expression.

When an expression is evaluated during execution, that is commonly
called "runtime".

Do those definition work for you?


If so, then I would offer this snippet of code as an example
of a "runtime" evaluation of the conversion from an integer
to a double:

Consider this snippet as the entire compilation unit, there
is nothing more in the input source file:

extern int i;
double foo(void)
{
double d;
d = i;
}

In this case, the compiler does not know, a-prior, the value of 'i',
and thus is obliged to produce code which will evaluate the
conversion at execution time. Therefor, following the definitions;
the conversion of 'i' from `int' to `double' is performed at runtime.

Does that sound right?

As a different example, lt's consider this:

double foo(void)
{
return 5;
}

In the C/C++ language, the expression "5" is defined to be an integer
constant.

Thus, the compiler, when processing this source, has the information
to convert the integer constant `5' (which comes from the expression "5")
to a double constant `5.0'. Thus, the compiler is not required to
produce
instructions that evaluate this conversion at execution time; it can
simply
use the "compile time" converted value. Note that, sometimes, the
compiler is not
obliged to use the "compile time" value (although the language standards
describe situations where it must...) so, frequently the evaluation of
expressions
at "compile time" is considered an optimization.

That is the idea I would like to follow when considering "compile time"
vs. "runtime".

Ok np.
Having said all of that; I'd hope these definitions of "compile time" and
"runtime"
will let us proceed with the other issues, and get back to the definitions
of arrays...

To return to that, do you agree that in this declaration:

int arr[5];

'arr' is the name of the contigous set of 5 `int' elements?

And, to go to the next step, would you agree that in this
declaration:

int i;

`i' is the name of single `int'?
Yes I agree, you may continue.
 
P

Paul

Leigh Johnston said:
You don't like abuse?

You posted the following in February to this very newsgroup:

"They lose an argument because I provide supporting links from Stroustrup
and intellegnet arguments, while they provide no more than, they know it
all therefor they are right, as an argument. They show nothing more than
fear , they are cowards and lack intelligence and wit. This forum has
turned into the most homosexual group of losers I ever seen in my life."

If you don't like abuse then perhaps you should stop with the abuse
yourself? A good start would be for you to try dealing with your own
homophobia. Also look up the word "hypocrisy" in a dictionary.

HTH.
Obviously this has hit a raw nerve with you.

If homosexuals now consider being called gay, abusive. Or homophobic or
whatever then thats not my problem. I don't care what is the latest trend on
gay street and what is or isn't considered acceptable to them.

Go find a suitable newsgroup.
 
I

Ian Collins

No that is your opinion.
Other people have different opinions and I happen to be one of those people.

I value the opinions of other professionals I have worked wit or known.
So tell me, how many x86 assembly projects have you worked on?
I have already posted a link to Randal Hydes Art of Assembly that describes
what a pointer is, and RH defines that a pointer can be a simple offset.

No, it does not. As usual you have chosen to misinterpret the link you
have posted.

So these are trusted sources? If so answer two is the same as mine,
answer one is specific to PIC and answer 3 is a little vague, but
contains the key phrase "with a width appropriate for the addressable
size of the memory segment". So a pointer could be say 1000H, which
could be used to address location 1000H with an immediate access, or
loaded to a register as indirect access. This is analogous to writing

char c = (char*)0x1000;

in C++.
These are hardware registers.

Correct, look at their names again.
The instruction

mov DWORD PTR _arr$[ebp], 0

given the definition of the constant _arr$

_arr$ = -12 ; size = 12

writes zero the the memory location who's address is ebp-12. Here ebp is
the pointer and -12 is the offset.

_arr$ is a label that equates to the value of (-12) .

That is what I said.
Here the label _arr$ is used as a pointer,

No it is used as an offer to a pointer.
The next assignment which is a bit messy in MASM,

mov DWORD PTR _arr$[ebp+4], eax

writes zero the the memory location who's address is ebp-12+4.

This confirms that _arr$ is an offset, which is used to create a memory
address. Therefore it's a pointer.

No it isn't. It's no more a pointer than the 1 in *(p+1) = 0;

No tell me again, how many x86 assembly projects have you worked on?
 
P

Paul

Ian Collins said:
I value the opinions of other professionals I have worked wit or known. So
tell me, how many x86 assembly projects have you worked on?


No, it does not. As usual you have chosen to misinterpret the link you
have posted.
I didn't interpret the link at all. I quoted it word for word.

So these are trusted sources? If so answer two is the same as mine,
answer one is specific to PIC and answer 3 is a little vague, but contains
the key phrase "with a width appropriate for the addressable size of the
memory segment". So a pointer could be say 1000H, which could be used to
address location 1000H with an immediate access, or loaded to a register
as indirect access. This is analogous to writing
Answer two is nothing like yours. Answer 2 states:
"Pointer is nothing but a unsigned integer indicating position in a memory
(virtual address space to be precise)."
char c = (char*)0x1000;

in C++.


Correct, look at their names again.

We are talking about pointers in software, not a hardware pointer.
The instruction

mov DWORD PTR _arr$[ebp], 0

given the definition of the constant _arr$

_arr$ = -12 ; size = 12

writes zero the the memory location who's address is ebp-12. Here ebp
is
the pointer and -12 is the offset.

_arr$ is a label that equates to the value of (-12) .

That is what I said.

You said this meant it was not not a pointer.
No it is used as an offer to a pointer.

It's used as an offset to a hardware pointer,because it points to an offset
in the stack frame.
This does not mean that the offset is not also pointer.
The next assignment which is a bit messy in MASM,

mov DWORD PTR _arr$[ebp+4], eax

writes zero the the memory location who's address is ebp-12+4.

This confirms that _arr$ is an offset, which is used to create a memory
address. Therefore it's a pointer.

No it isn't. It's no more a pointer than the 1 in *(p+1) = 0;

No its more like:
const int offset_to_array = 1;
(p+offset_to_array)
No tell me again, how many x86 assembly projects have you worked on?

Since when was this discussion limited to x86 processors?
 
P

Paul

Leigh Johnston said:
You really are dumb aren't you? You were obviously trying to use the
words "homosexual" or "gay" as an insult which is homophobic, i.e.
implying that being homosexual is somehow a negative thing making it
suitable to be an insult in your tiny mind.

But you are correct this is off-topic just stop being such a fucking
hypocrite.

BTW this is a perfect opportunity for you to apologize if you are man
enough.
Like i said if you wish to discuss these kind of things you should go find a
suitable newsgroup. It does not interest me.
 
P

Paul

Ian Collins said:
So offset_to_array is a pointer and 1 isn't? Interesting.
offset_to_array is a pointer yes. because its value represents another
memory location. It points to that location, albeit an offset to the
location , it still points there.

1 is a number, more specifically its an integer.
 
I

Ian Collins

offset_to_array is a pointer yes. because its value represents another
memory location. It points to that location, albeit an offset to the
location , it still points there.

1 is a number, more specifically its an integer.

Well well. I think we'll leave it there before this degenerates further
into farce.

So tell me, how many software projects have you worked on? It's clear
youve never done any assembly programming, how about C++?
 
P

Paul

Ian Collins said:
Well well. I think we'll leave it there before this degenerates further
into farce. Yes you do that.

So tell me, how many software projects have you worked on? It's clear
youve never done any assembly programming, how about C++?
5327 .
How many have you worked on?
 
T

Thomas David Rivers

Paul said:
To return to that, do you agree that in this declaration:

int arr[5];

'arr' is the name of the contigous set of 5 `int' elements?

And, to go to the next step, would you agree that in this
declaration:

int i;

`i' is the name of single `int'?
Yes I agree, you may continue.



So - we should then consider something fairly important... what does
"name" mean?

I would ask that we consider the 'name' of something to be the
designation of the location that contains that 'something'. And, I want
to movitave that definition with the following scenario.

If we can imagine that variables, in the C/C++ sense, are simply
"boxes" that contain their values - like shoeboxes on a shelf,
then the "name" associated with the variable is simply the name
associated with a "box." Let's imagine that this shelf can contain
many boxes, and that the boxes are numbered... box #0, box #1, box #2..

A box can be referred to by its number - its location on the shelf, or if
we associate a name with a box #; we can use the name. For example,
box #51 might have the name `i' associated with it.

Thus, if we consider this snippet of C code:


int i;
i = 5;

the semantics of that would be something similar to:

define a box name 'i', allocate space for it, let's say that is box
#51, associate
location #51 with the name 'i'.

produce the manifest `int' constant 5
Find the box with the name 'i', oh - it's box #51.
store the manifest constant 5 into box #51.



Similarly, the snippet:

int i,j;
i = j;

might be realized in this way:

define a box named 'i' that can contain int-typed objects, say, box #51.
define a box named 'j' that can contain int-typed objects, say, box #52.

Given the name 'j'; find its box - oh - it's box #52.
Retrieve (fetch) the value from box #52.
Given the name 'i'; find its box - oh - it's box #51.
Store the value previously fetched value into box #51.


So far, I've only talked about boxes that can contain `int'-typed values.

Let's introduce a new box, and say that it can contain the location (the
box #)
of another box, and the other box can contain `int'-typed values. We would
call this new box a "pointer" to an `int'-typed box, because it doesn't
contain
the `int'-type value itself, but instead tells us the location (the box
#) of the
value.

Now - let's consider this:

int *ip;
int i;

ip = &i;

in this mindset - what does this mean? To discuss this, we need to define
the &-operator. Le's say that the &-operator is named 'address of' and that
it returns the location (the box #) of its operand. Say, for example,
if `i'
happened to be box #51, then the expression "&i" would produce location #51.

Remember - I can have two kinds of boxes on my shelf, boxes that contain
`int'-typed values, and boxes that contain the location of other
`int'-typed boxes.
So, &i doesn't produce an `int'-typed value, it produces a location. In
this
example, it produced #51. (I have been careful to use '#' to indicate
location numbers
instead of simple `int'-typed values.. this distinction will become
important.)

So - the semantics of that statement would be (if I may be so bold
as to be a little loose on the details):

define a box named 'ip' - it can contain the location of other
`int'-typed boxes,
let's say it is box #52.
define a box named 'i' - it can contain `int' values, let's say it's
box #51.

Apply the &-operator to the box named `i' - oh - i is box #51, so &i
produces
the location #51.
Look up the name `ip - oh - that's box #52.
Store our previously found location (#51) into box #52.


OK - now - let's say that I happen to buy my boxes from a manufacturer that
can only make 2-kinds of boxes, those boxes that can contain `int' elements,
and those boxes that can contain the location of other boxes that contain
`int' elements. (that is, `int' boxes and `int *' boxes).

So, let's look at this:

int *ip;
int arr[5];


What can this do? I propose it does the following:

define a box named 'ip', that box is allowed to contain the location of
other `int'-type boxes; let's say that is box #52.
define a space of 5 boxes, each of these boxes is on the shelf starting
at, say, location #53. Each of these boxes is an `int'-typed
box. The
boxes are contiguous, starting a location #53 and going thru location
#57 (inclusive.) Since `arr' (at the C/C++ level) is a single
object,
the location associated with `arr' is #53 (the start of the 5
contiguous
boxes on the shelf.)

That is, in this scenario, the location of 'ip' is box #52, the
location of 'arr'
is box #53. `ip' uses one box, `arr' uses 5 boxes.

With this, we can provide a definition of "name".... the "name" of the
variable
provides a mechanism for finding precisely which "box" (the box #, or
location
of the box) houses the value of the variable. The "name" is nothing
more than
a convenience for mapping the location of the variable.

So - in our example, the name 'ip' is asociated with box #52, the name 'arr'
is associated with box #53.

Before I go on, I want to check to see if you agree with everything so
far...

- Dave Rivers -
 
Ö

Öö Tiib

--His reason for believing so is one part of the C++ standard which
--mentions that array objects are not modifiable.

No you are incorrect. My opinion that the object 'arr' and the 5 contiguous
integer objects are different entites is bases on the fact that they contain
contain different values.

in the following code:
int arr[5]={0};
std::cout<< arr;
std::cout<< arr[0];

The value accessed by arr is not any value that is stored within the 5
contiguous integer objects.
If 'arr' was truly the same as the 5 integer objects then it would store the
same value.

Of course, arr stores all of them 5 integer objects. It is array after
all. Your example does not show it since ostream is not made to
display whole arrays. ostream can display a void* and that is into
what any array converts to as soon someone coughs at it (bloody legacy
from C). But we can help ostream out easily to accept int arrays too.
See:

#include<iostream>

/// Helping poor ostream to output int arrays
template<int N>
std::eek:stream& operator<<( std::eek:stream& o, int const (& a)[N] )
{
o << "{";
for ( int i = 0; i < N; ++i )
{
o << a;
if ( i < N-1 ) o << ",";
}
o << "}";
return o;
}

int main()
{
// Pauls code
int arr[5]={0};
std::cout << "arr =" << arr << std::endl;
std::cout << "arr[0] =" << arr[0] << std::endl;
// that is what arr converted to without our operator
std::cout << "&arr[0] = " << &arr[0] << std::endl;
}

The output is:

arr = {0,0,0,0,0}
arr[0] = 0
&arr[0] = 0012FF50

arr is still array of 5 ints. Can't be Paul you are arguing even
against that?
 
P

Paul

Thomas David Rivers said:
Paul said:
To return to that, do you agree that in this declaration:

int arr[5];

'arr' is the name of the contigous set of 5 `int' elements?

And, to go to the next step, would you agree that in this
declaration:

int i;

`i' is the name of single `int'?
Yes I agree, you may continue.



So - we should then consider something fairly important... what does
"name" mean?

I would ask that we consider the 'name' of something to be the
designation of the location that contains that 'something'. And, I want
to movitave that definition with the following scenario.

If we can imagine that variables, in the C/C++ sense, are simply
"boxes" that contain their values - like shoeboxes on a shelf,
then the "name" associated with the variable is simply the name
associated with a "box." Let's imagine that this shelf can contain
many boxes, and that the boxes are numbered... box #0, box #1, box #2..

A box can be referred to by its number - its location on the shelf, or if
we associate a name with a box #; we can use the name. For example,
box #51 might have the name `i' associated with it.

Thus, if we consider this snippet of C code:


int i;
i = 5;

the semantics of that would be something similar to:

define a box name 'i', allocate space for it, let's say that is box #51,
associate
location #51 with the name 'i'.

produce the manifest `int' constant 5
Find the box with the name 'i', oh - it's box #51.
store the manifest constant 5 into box #51.



Similarly, the snippet:

int i,j;
i = j;

might be realized in this way:

define a box named 'i' that can contain int-typed objects, say, box #51.
define a box named 'j' that can contain int-typed objects, say, box #52.

Given the name 'j'; find its box - oh - it's box #52.
Retrieve (fetch) the value from box #52.
Given the name 'i'; find its box - oh - it's box #51.
Store the value previously fetched value into box #51.


So far, I've only talked about boxes that can contain `int'-typed values.

Let's introduce a new box, and say that it can contain the location (the
box #)
of another box, and the other box can contain `int'-typed values. We
would
call this new box a "pointer" to an `int'-typed box, because it doesn't
contain
the `int'-type value itself, but instead tells us the location (the box #)
of the
value.

Now - let's consider this:

int *ip;
int i;

ip = &i;

in this mindset - what does this mean? To discuss this, we need to define
the &-operator. Le's say that the &-operator is named 'address of' and
that
it returns the location (the box #) of its operand. Say, for example, if
`i'
happened to be box #51, then the expression "&i" would produce location
#51.

Remember - I can have two kinds of boxes on my shelf, boxes that contain
`int'-typed values, and boxes that contain the location of other
`int'-typed boxes.
So, &i doesn't produce an `int'-typed value, it produces a location. In
this
example, it produced #51. (I have been careful to use '#' to indicate
location numbers
instead of simple `int'-typed values.. this distinction will become
important.)

So - the semantics of that statement would be (if I may be so bold
as to be a little loose on the details):

define a box named 'ip' - it can contain the location of other
`int'-typed boxes,
let's say it is box #52.
define a box named 'i' - it can contain `int' values, let's say it's box
#51.

Apply the &-operator to the box named `i' - oh - i is box #51, so &i
produces
the location #51.
Look up the name `ip - oh - that's box #52.
Store our previously found location (#51) into box #52.


OK - now - let's say that I happen to buy my boxes from a manufacturer
that
can only make 2-kinds of boxes, those boxes that can contain `int'
elements,
and those boxes that can contain the location of other boxes that contain
`int' elements. (that is, `int' boxes and `int *' boxes).
So, let's look at this:

int *ip;
int arr[5];


What can this do? I propose it does the following:

define a box named 'ip', that box is allowed to contain the location
of
other `int'-type boxes; let's say that is box #52.
define a space of 5 boxes, each of these boxes is on the shelf
starting
at, say, location #53. Each of these boxes is an `int'-typed box.
The
boxes are contiguous, starting a location #53 and going thru
location
#57 (inclusive.) Since `arr' (at the C/C++ level) is a single
object,
the location associated with `arr' is #53 (the start of the 5
contiguous
boxes on the shelf.)

That is, in this scenario, the location of 'ip' is box #52, the location
of 'arr'
is box #53. `ip' uses one box, `arr' uses 5 boxes.

With this, we can provide a definition of "name".... the "name" of the
variable
provides a mechanism for finding precisely which "box" (the box #, or
location
of the box) houses the value of the variable. The "name" is nothing more
than
a convenience for mapping the location of the variable.
So - in our example, the name 'ip' is asociated with box #52, the name
'arr'
is associated with box #53.

Before I go on, I want to check to see if you agree with everything so
far...
I agree with you that the "name" provides a mechanisn for mapping the
location but....
The names 'i', 'ip' and 'arr' have different name mechanisms.
The name 'i' refers to box#51, when used in an expression it evaluates to
whatever is contained in box#51.
The name 'ip' refers to box#52, it evaluates to whatever is contained in
box#52.

The name 'arr' refers to box#53.... but it does not evaluate to the contents
of box#53. It evaluates to the address of box#53.
 
P

Paul

--His reason for believing so is one part of the C++ standard which
--mentions that array objects are not modifiable.

No you are incorrect. My opinion that the object 'arr' and the 5
contiguous
integer objects are different entites is bases on the fact that they
contain
contain different values.

in the following code:
int arr[5]={0};
std::cout<< arr;
std::cout<< arr[0];

The value accessed by arr is not any value that is stored within the 5
contiguous integer objects.
If 'arr' was truly the same as the 5 integer objects then it would store
the
same value.

--Of course, arr stores all of them 5 integer objects. It is array after
--all. Your example does not show it since ostream is not made to
--display whole arrays. ostream can display a void* and that is into
--what any array converts to as soon someone coughs at it (bloody legacy
--from C). But we can help ostream out easily to accept int arrays too.
--See:

--#include<iostream>

--/// Helping poor ostream to output int arrays
-- template<int N>
-- std::eek:stream& operator<<( std::eek:stream& o, int const (& a)[N] )
-- {
-- o << "{";
-- for ( int i = 0; i < N; ++i )
-- {
-- o << a;
-- if ( i < N-1 ) o << ",";
-- }
-- o << "}";
-- return o;
-- }
--
-- int main()
-- {
-- // Pauls code
-- int arr[5]={0};
-- std::cout << "arr =" << arr << std::endl;
-- std::cout << "arr[0] =" << arr[0] << std::endl;
-- // that is what arr converted to without our operator
-- std::cout << "&arr[0] = " << &arr[0] << std::endl;
-- }

--The output is:

--arr = {0,0,0,0,0}
--arr[0] = 0
--&arr[0] = 0012FF50

-- arr is still array of 5 ints. Can't be Paul you are arguing even
--against that?


The problem is not just ostream operator << , its every operator in the C++
language.

The identifier 'arr' is evaluated as an addresss in almost all situations
except typeid and sizeof:
int* p= arr; //This works
int x = arr; //This does not work


Also consider this :
template <typename T>
void foo(T t){
std::cout<< typeid(t).name();
}
foo(arr);
Given a free choice arr is passed as a pointer and not a reference.

The identifier 'arr' does not behave like identifiers to other objects in
C++ it is somewhat special.
I can agree that it is a non modifiable array-type object. But it does not
identify an array in the same sense that other objects' names identify them,
it indirectly identifies the array, because it must be dereferenced to
access the array of objects that it identifies.
 
T

Thomas David Rivers

Paul said:
Paul said:
To return to that, do you agree that in this declaration:

int arr[5];

'arr' is the name of the contigous set of 5 `int' elements?

And, to go to the next step, would you agree that in this
declaration:

int i;

`i' is the name of single `int'?

Yes I agree, you may continue.




So - we should then consider something fairly important... what does
"name" mean?

I would ask that we consider the 'name' of something to be the
designation of the location that contains that 'something'. And, I want
to movitave that definition with the following scenario.

If we can imagine that variables, in the C/C++ sense, are simply
"boxes" that contain their values - like shoeboxes on a shelf,
then the "name" associated with the variable is simply the name
associated with a "box." Let's imagine that this shelf can contain
many boxes, and that the boxes are numbered... box #0, box #1, box #2..

A box can be referred to by its number - its location on the shelf,
or if
we associate a name with a box #; we can use the name. For example,
box #51 might have the name `i' associated with it.

Thus, if we consider this snippet of C code:


int i;
i = 5;

the semantics of that would be something similar to:

define a box name 'i', allocate space for it, let's say that is box
#51, associate
location #51 with the name 'i'.

produce the manifest `int' constant 5
Find the box with the name 'i', oh - it's box #51.
store the manifest constant 5 into box #51.



Similarly, the snippet:

int i,j;
i = j;

might be realized in this way:

define a box named 'i' that can contain int-typed objects, say, box
#51.
define a box named 'j' that can contain int-typed objects, say, box
#52.

Given the name 'j'; find its box - oh - it's box #52.
Retrieve (fetch) the value from box #52.
Given the name 'i'; find its box - oh - it's box #51.
Store the value previously fetched value into box #51.


So far, I've only talked about boxes that can contain `int'-typed
values.

Let's introduce a new box, and say that it can contain the location
(the box #)
of another box, and the other box can contain `int'-typed values. We
would
call this new box a "pointer" to an `int'-typed box, because it
doesn't contain
the `int'-type value itself, but instead tells us the location (the
box #) of the
value.

Now - let's consider this:

int *ip;
int i;

ip = &i;

in this mindset - what does this mean? To discuss this, we need to
define
the &-operator. Le's say that the &-operator is named 'address of'
and that
it returns the location (the box #) of its operand. Say, for
example, if `i'
happened to be box #51, then the expression "&i" would produce
location #51.

Remember - I can have two kinds of boxes on my shelf, boxes that contain
`int'-typed values, and boxes that contain the location of other
`int'-typed boxes.
So, &i doesn't produce an `int'-typed value, it produces a location.
In this
example, it produced #51. (I have been careful to use '#' to
indicate location numbers
instead of simple `int'-typed values.. this distinction will become
important.)

So - the semantics of that statement would be (if I may be so bold
as to be a little loose on the details):

define a box named 'ip' - it can contain the location of other
`int'-typed boxes,
let's say it is box #52.
define a box named 'i' - it can contain `int' values, let's say it's
box #51.

Apply the &-operator to the box named `i' - oh - i is box #51, so
&i produces
the location #51.
Look up the name `ip - oh - that's box #52.
Store our previously found location (#51) into box #52.


OK - now - let's say that I happen to buy my boxes from a
manufacturer that
can only make 2-kinds of boxes, those boxes that can contain `int'
elements,
and those boxes that can contain the location of other boxes that
contain
`int' elements. (that is, `int' boxes and `int *' boxes).
So, let's look at this:

int *ip;
int arr[5];


What can this do? I propose it does the following:

define a box named 'ip', that box is allowed to contain the
location of
other `int'-type boxes; let's say that is box #52.
define a space of 5 boxes, each of these boxes is on the shelf
starting
at, say, location #53. Each of these boxes is an `int'-typed
box. The
boxes are contiguous, starting a location #53 and going thru
location
#57 (inclusive.) Since `arr' (at the C/C++ level) is a single
object,
the location associated with `arr' is #53 (the start of the 5
contiguous
boxes on the shelf.)

That is, in this scenario, the location of 'ip' is box #52, the
location of 'arr'
is box #53. `ip' uses one box, `arr' uses 5 boxes.

With this, we can provide a definition of "name".... the "name" of
the variable
provides a mechanism for finding precisely which "box" (the box #, or
location
of the box) houses the value of the variable. The "name" is nothing
more than
a convenience for mapping the location of the variable.
So - in our example, the name 'ip' is asociated with box #52, the
name 'arr'
is associated with box #53.

Before I go on, I want to check to see if you agree with everything
so far...
I agree with you that the "name" provides a mechanisn for mapping the
location but....
The names 'i', 'ip' and 'arr' have different name mechanisms.
The name 'i' refers to box#51, when used in an expression it evaluates
to whatever is contained in box#51.
The name 'ip' refers to box#52, it evaluates to whatever is contained
in box#52.

The name 'arr' refers to box#53.... but it does not evaluate to the
contents of box#53. It evaluates to the address of box#53.

I left all of the context above, so we have something to refer to....

And - yes - you are absolutely right... the name 'arr' refers to the
start of
the array... that is; as you correctly point out above; 'arr' would
refer to box #53.
To echo your statement, the name 'arr' does not refer to the contents of
boxes #53 thru #57 - it, in many contexts, refers to the location #53.
Similarly, the name 'ip' denotes box #52... but, as you correctly point out,
the context in which the name is referenced is key to understanding what is
happening.

For example, in this snippet:

int i, j;
i = j;

On the right-hand-side of the assignment operator, we find 'j' - that refers
to the contents of the box at the location associated with the name
'j'. In C, we call
that an "rvalue". On the left-hand-side, we find 'i'. That refers to
the location of 'i',
the location used for storing the value computed on the
right-hand-side. In C, we call than an "lvalue". Note that, in both
instances, the names do refer to the location
of the boxes - it is simply what is done with that location that
changes. In the rvalue
context, we fetch the contents of the box, on the lvalue side, we store
the value into
the box.

(Note that 'j' in the assignment expression is first an "lvalue" and is
converted
into an "rvalue" by the rules of the language. It is this treatment
that indicates
that the value is to be retrieved from the box.)

As you mentioned above, the context is critical to understanding what is
going
on. I commend you on recognizing that distinction.

Thus - we now need to consider what it means in C/C++ when we encounter
an expression using the name of an array.

The way this is encapsulated in the C/C++ language is the rule regarding
conversion of an lvalue with an array type to a pointer to the first element
of the array.

So - if we now consider this:

int *ip;
int arr[5];

ip = arr;

What would happen in our "shoebox" world? If we use your absolutely
correct
observation, then it would be this:

define a box named "ip", say - box #52 - that box can contain the
location of
other `int'-typed boxes
define a space of 5 boxes, beginning at box #53 thru box #57; name that
area 'arr' by associating 'arr' with box #53

Now - how do we evaluate the expression "arr" in the context of the
assignment statement? Well, according to the C language rules, when
you discover an lvalue that has a type 'array'; you convert that into
the address of its first element.

Thus, we can say that:

ip = arr;

can be evaluated as:

Look up the name 'arr' - oh, it is an array of 5 `int'-typed
boxes. According
to the rules, in this context, we should produce the location of the
first box of the array, that would be location #53.
Look up the name 'ip' - oh - that is a box (at location #52) that
can contain the location
of other `int'-typed boxes.
Store the value previously found location (#53) into box #52.

As you had correctly forseen, we are able to evaluate this using the rules
of the programming language.

Note that, there wasn't a "extra" shoebox allocated/needed to produce
the result.

Note that the 'name' did not mean some other space was allocated... it
simply
refers to the location, as we have previously shown/agreed to.

If you can agree with this, then we can move on to other interesting items.

- Dave Rivers -
 
Ö

Öö Tiib

"Joshua Maurice" <[email protected]> wrote in message
--His reason for believing so is one part of the C++ standard which
--mentions that array objects are not modifiable.
No you are incorrect. My opinion that the object 'arr' and the 5
contiguous
integer objects are different entites is bases on the fact that they
contain
contain different values.
in the following code:
int arr[5]={0};
std::cout<< arr;
std::cout<< arr[0];
The value accessed by arr is not any value that is stored within the 5
contiguous integer objects.
If 'arr' was truly the same as the 5 integer objects then it would store
the
same value.

--Of course, arr stores all of them 5 integer objects. It is array after
--all. Your example does not show it since ostream is not made to
--display whole arrays. ostream can display a void* and that is into
--what any array converts to as soon someone coughs at it (bloody legacy
--from C). But we can help ostream out easily to accept int arrays too.
--See:

 --#include<iostream>

 --/// Helping poor ostream to output int arrays
-- template<int N>
-- std::eek:stream& operator<<( std::eek:stream& o, int const (& a)[N] )
-- {
--     o << "{";
--     for ( int i = 0; i < N; ++i )
--     {
--         o << a;
--         if ( i < N-1 ) o << ",";
--     }
--    o << "}";
--     return o;
-- }
--
-- int main()
-- {
--     // Pauls code
--     int arr[5]={0};
--     std::cout << "arr =" << arr << std::endl;
--     std::cout << "arr[0] =" << arr[0] << std::endl;
--     // that is what arr converted to without our operator
--     std::cout << "&arr[0] = " << &arr[0] << std::endl;
-- }

--The output is:

--arr = {0,0,0,0,0}
--arr[0] = 0
--&arr[0] = 0012FF50

-- arr is still array of 5 ints. Can't be Paul you are arguing even
--against that?

The problem is not just ostream operator << , its every operator in the C++
language.


Yes. Lot of smart people have felt that it is a problem and made
classes to wrap raw arrays so to get rid of it in C++. Usage of raw
arrays in real C++ production code is relatively low these days.
The identifier 'arr' is evaluated as an addresss in almost all situations
except typeid and sizeof:
int* p= arr;  //This works
int x = arr;  //This does not work

The 'p = arr' works, thanks to implicit arr to &arr[0] conversion. My
template above does not accept 'p' as int array argument anymore since
it is a true raw pointer unlike 'arr'. 'p' goes to cout as usual
void*. The 'x = arr' should indeed not to work because assigning whole
array to single int does not make sense.
Also consider this :
template <typename T>
void foo(T t){
 std::cout<< typeid(t).name();}

foo(arr);
Given a free choice arr is passed as a pointer and not a reference.

Yes. That is because C did not have references, so there were only two
ways to pass arrays in C (1) as pointer to first element (+ size as
separate argument) or (2) as member of struct. Both ways are indirect.
So the C designer's felt that writing '&arr[0]' everytime they needed
a pointer to first element of array too verbose syntax. C++ did not
change that because one of objectives of C++ is making migrating from
C to C++ as painless as possible and that is achieved by making most C
code to compile with C++ compiler.
The identifier 'arr' does not behave like identifiers to other objects in
C++ it is somewhat special.
I can agree that it is a non modifiable array-type object. But it does not
identify an array in the same sense that other objects' names identify them,
it indirectly identifies the array, because it must be dereferenced to
access the array of objects that it identifies.

Yes, the pointer to what array implicitly converts (as it only can)
indirectly identifies the array. However array itself is located in
memory exactly where it's elements are, starting from first element.
Consider the code:

    int arr[5]={0};
    std::cout << "&arr[0] = " << &arr[0] << std::endl;
    std::cout << "&arr = " << &arr << std::endl;

By language rules the address of first element of array and address of
array itself are same. So arr is object consisting of 5 ints and not a
separate pointer-like object (residing in memory elsewhere) that
points to the ints.
 
P

Paul

Thomas David Rivers said:
Paul said:
To return to that, do you agree that in this declaration:

int arr[5];

'arr' is the name of the contigous set of 5 `int' elements?

And, to go to the next step, would you agree that in this
declaration:

int i;

`i' is the name of single `int'?

Yes I agree, you may continue.




So - we should then consider something fairly important... what does
"name" mean?

I would ask that we consider the 'name' of something to be the
designation of the location that contains that 'something'. And, I want
to movitave that definition with the following scenario.

If we can imagine that variables, in the C/C++ sense, are simply
"boxes" that contain their values - like shoeboxes on a shelf,
then the "name" associated with the variable is simply the name
associated with a "box." Let's imagine that this shelf can contain
many boxes, and that the boxes are numbered... box #0, box #1, box #2..

A box can be referred to by its number - its location on the shelf, or
if
we associate a name with a box #; we can use the name. For example,
box #51 might have the name `i' associated with it.

Thus, if we consider this snippet of C code:


int i;
i = 5;

the semantics of that would be something similar to:

define a box name 'i', allocate space for it, let's say that is box
#51, associate
location #51 with the name 'i'.

produce the manifest `int' constant 5
Find the box with the name 'i', oh - it's box #51.
store the manifest constant 5 into box #51.



Similarly, the snippet:

int i,j;
i = j;

might be realized in this way:

define a box named 'i' that can contain int-typed objects, say, box
#51.
define a box named 'j' that can contain int-typed objects, say, box
#52.

Given the name 'j'; find its box - oh - it's box #52.
Retrieve (fetch) the value from box #52.
Given the name 'i'; find its box - oh - it's box #51.
Store the value previously fetched value into box #51.


So far, I've only talked about boxes that can contain `int'-typed
values.

Let's introduce a new box, and say that it can contain the location (the
box #)
of another box, and the other box can contain `int'-typed values. We
would
call this new box a "pointer" to an `int'-typed box, because it doesn't
contain
the `int'-type value itself, but instead tells us the location (the box
#) of the
value.

Now - let's consider this:

int *ip;
int i;

ip = &i;

in this mindset - what does this mean? To discuss this, we need to
define
the &-operator. Le's say that the &-operator is named 'address of' and
that
it returns the location (the box #) of its operand. Say, for example,
if `i'
happened to be box #51, then the expression "&i" would produce location
#51.

Remember - I can have two kinds of boxes on my shelf, boxes that contain
`int'-typed values, and boxes that contain the location of other
`int'-typed boxes.
So, &i doesn't produce an `int'-typed value, it produces a location. In
this
example, it produced #51. (I have been careful to use '#' to indicate
location numbers
instead of simple `int'-typed values.. this distinction will become
important.)

So - the semantics of that statement would be (if I may be so bold
as to be a little loose on the details):

define a box named 'ip' - it can contain the location of other
`int'-typed boxes,
let's say it is box #52.
define a box named 'i' - it can contain `int' values, let's say it's
box #51.

Apply the &-operator to the box named `i' - oh - i is box #51, so &i
produces
the location #51.
Look up the name `ip - oh - that's box #52.
Store our previously found location (#51) into box #52.


OK - now - let's say that I happen to buy my boxes from a manufacturer
that
can only make 2-kinds of boxes, those boxes that can contain `int'
elements,
and those boxes that can contain the location of other boxes that
contain
`int' elements. (that is, `int' boxes and `int *' boxes).
So, let's look at this:

int *ip;
int arr[5];


What can this do? I propose it does the following:

define a box named 'ip', that box is allowed to contain the location
of
other `int'-type boxes; let's say that is box #52.
define a space of 5 boxes, each of these boxes is on the shelf
starting
at, say, location #53. Each of these boxes is an `int'-typed box.
The
boxes are contiguous, starting a location #53 and going thru
location
#57 (inclusive.) Since `arr' (at the C/C++ level) is a single
object,
the location associated with `arr' is #53 (the start of the 5
contiguous
boxes on the shelf.)

That is, in this scenario, the location of 'ip' is box #52, the
location of 'arr'
is box #53. `ip' uses one box, `arr' uses 5 boxes.

With this, we can provide a definition of "name".... the "name" of the
variable
provides a mechanism for finding precisely which "box" (the box #, or
location
of the box) houses the value of the variable. The "name" is nothing
more than
a convenience for mapping the location of the variable.
So - in our example, the name 'ip' is asociated with box #52, the name
'arr'
is associated with box #53.

Before I go on, I want to check to see if you agree with everything so
far...
I agree with you that the "name" provides a mechanisn for mapping the
location but....
The names 'i', 'ip' and 'arr' have different name mechanisms.
The name 'i' refers to box#51, when used in an expression it evaluates to
whatever is contained in box#51.
The name 'ip' refers to box#52, it evaluates to whatever is contained in
box#52.

The name 'arr' refers to box#53.... but it does not evaluate to the
contents of box#53. It evaluates to the address of box#53.

I left all of the context above, so we have something to refer to....

And - yes - you are absolutely right... the name 'arr' refers to the
start of
the array... that is; as you correctly point out above; 'arr' would refer
to box #53.
To echo your statement, the name 'arr' does not refer to the contents of
boxes #53 thru #57 - it, in many contexts, refers to the location #53.
Similarly, the name 'ip' denotes box #52... but, as you correctly point
out,
the context in which the name is referenced is key to understanding what
is
happening.

For example, in this snippet:

int i, j;
i = j;

On the right-hand-side of the assignment operator, we find 'j' - that
refers
to the contents of the box at the location associated with the name 'j'.
In C, we call
that an "rvalue". On the left-hand-side, we find 'i'. That refers to the
location of 'i',
the location used for storing the value computed on the right-hand-side.
In C, we call than an "lvalue". Note that, in both instances, the names
do refer to the location
of the boxes - it is simply what is done with that location that changes.
In the rvalue
context, we fetch the contents of the box, on the lvalue side, we store
the value into
the box.

(Note that 'j' in the assignment expression is first an "lvalue" and is
converted
into an "rvalue" by the rules of the language. It is this treatment that
indicates
that the value is to be retrieved from the box.)

As you mentioned above, the context is critical to understanding what is
going
on. I commend you on recognizing that distinction.

Thus - we now need to consider what it means in C/C++ when we encounter
an expression using the name of an array.

The way this is encapsulated in the C/C++ language is the rule regarding
conversion of an lvalue with an array type to a pointer to the first
element
of the array.

So - if we now consider this:

int *ip;
int arr[5];

ip = arr;

What would happen in our "shoebox" world? If we use your absolutely
correct
observation, then it would be this:

define a box named "ip", say - box #52 - that box can contain the
location of
other `int'-typed boxes
define a space of 5 boxes, beginning at box #53 thru box #57; name
that
area 'arr' by associating 'arr' with box #53

Now - how do we evaluate the expression "arr" in the context of the
assignment statement? Well, according to the C language rules, when
you discover an lvalue that has a type 'array'; you convert that into
the address of its first element.

Thus, we can say that:

ip = arr;

can be evaluated as:

Look up the name 'arr' - oh, it is an array of 5 `int'-typed boxes.
According
to the rules, in this context, we should produce the location of the
first box of the array, that would be location #53.
Look up the name 'ip' - oh - that is a box (at location #52) that can
contain the location
of other `int'-typed boxes.
Store the value previously found location (#53) into box #52.

As you had correctly forseen, we are able to evaluate this using the rules
of the programming language.

Note that, there wasn't a "extra" shoebox allocated/needed to produce the
result.

Note that the 'name' did not mean some other space was allocated... it
simply
refers to the location, as we have previously shown/agreed to.

This behaviour is different to other C++ names.
For example given the name of an int or an int*:

int x=7;
int* p =7;

When we use the names of a object in C++ we expect the the object to be
addressed and the value accessed whether it be a read or write operation.
With an arr the situation is different , when we use the name of an array we
do not expect the array to be addressed , instead we expect a pointer to the
array:
int* = arr;

The identifier or name 'arr' refers to an array of objects yet somehow its
value is an address , not the same value as any of the objects it refers to.







In C++
 
P

Paul

Öö Tiib said:
"Joshua Maurice" <[email protected]> wrote in message
--His reason for believing so is one part of the C++ standard which
--mentions that array objects are not modifiable.
No you are incorrect. My opinion that the object 'arr' and the 5
contiguous
integer objects are different entites is bases on the fact that they
contain
contain different values.
in the following code:
int arr[5]={0};
std::cout<< arr;
std::cout<< arr[0];
The value accessed by arr is not any value that is stored within the 5
contiguous integer objects.
If 'arr' was truly the same as the 5 integer objects then it would store
the
same value.

--Of course, arr stores all of them 5 integer objects. It is array after
--all. Your example does not show it since ostream is not made to
--display whole arrays. ostream can display a void* and that is into
--what any array converts to as soon someone coughs at it (bloody legacy
--from C). But we can help ostream out easily to accept int arrays too.
--See:

--#include<iostream>

--/// Helping poor ostream to output int arrays
-- template<int N>
-- std::eek:stream& operator<<( std::eek:stream& o, int const (& a)[N] )
-- {
-- o << "{";
-- for ( int i = 0; i < N; ++i )
-- {
-- o << a;
-- if ( i < N-1 ) o << ",";
-- }
-- o << "}";
-- return o;
-- }
--
-- int main()
-- {
-- // Pauls code
-- int arr[5]={0};
-- std::cout << "arr =" << arr << std::endl;
-- std::cout << "arr[0] =" << arr[0] << std::endl;
-- // that is what arr converted to without our operator
-- std::cout << "&arr[0] = " << &arr[0] << std::endl;
-- }

--The output is:

--arr = {0,0,0,0,0}
--arr[0] = 0
--&arr[0] = 0012FF50

-- arr is still array of 5 ints. Can't be Paul you are arguing even
--against that?

The problem is not just ostream operator << , its every operator in the
C++
language.


Yes. Lot of smart people have felt that it is a problem and made
classes to wrap raw arrays so to get rid of it in C++. Usage of raw
arrays in real C++ production code is relatively low these days.
The identifier 'arr' is evaluated as an addresss in almost all situations
except typeid and sizeof:
int* p= arr; //This works
int x = arr; //This does not work

--The 'p = arr' works, thanks to implicit arr to &arr[0] conversion. My
--template above does not accept 'p' as int array argument anymore since
--it is a true raw pointer unlike 'arr'. 'p' goes to cout as usual
--void*. The 'x = arr' should indeed not to work because assigning whole
--array to single int does not make sense.
Also consider this :
template <typename T>
void foo(T t){
std::cout<< typeid(t).name();}

foo(arr);
Given a free choice arr is passed as a pointer and not a reference.

--Yes. That is because C did not have references, so there were only two
--ways to pass arrays in C (1) as pointer to first element (+ size as
--separate argument) or (2) as member of struct. Both ways are indirect.
--So the C designer's felt that writing '&arr[0]' everytime they needed
--a pointer to first element of array too verbose syntax. C++ did not
--change that because one of objectives of C++ is making migrating from
--C to C++ as painless as possible and that is achieved by making most C
--code to compile with C++ compiler.
The identifier 'arr' does not behave like identifiers to other objects in
C++ it is somewhat special.
I can agree that it is a non modifiable array-type object. But it does not
identify an array in the same sense that other objects' names identify
them,
it indirectly identifies the array, because it must be dereferenced to
access the array of objects that it identifies.

--Yes, the pointer to what array implicitly converts (as it only can)
--indirectly identifies the array. However array itself is located in
--memory exactly where it's elements are, starting from first element.
--Consider the code:

-- int arr[5]={0};
-- std::cout << "&arr[0] = " << &arr[0] << std::endl;
-- std::cout << "&arr = " << &arr << std::endl;

--By language rules the address of first element of array and address of
--array itself are same. So arr is object consisting of 5 ints and not a
--separate pointer-like object (residing in memory elsewhere) that
--points to the ints.

Its nothing to do with language rules its to do with the hardware abilities.
It is not possible to address an array as one complete entity, unless it's
size one or something silly.

An array is not an addressable object therefore in C++ an object
representation is created by the compiler .
 
P

Paul

Leigh Johnston said:
--His reason for believing so is one part of the C++ standard which
--mentions that array objects are not modifiable.

No you are incorrect. My opinion that the object 'arr' and the 5
contiguous
integer objects are different entites is bases on the fact that they
contain
contain different values.

in the following code:
int arr[5]={0};
std::cout<< arr;
std::cout<< arr[0];

The value accessed by arr is not any value that is stored within the 5
contiguous integer objects.
If 'arr' was truly the same as the 5 integer objects then it would
store
the
same value.

--Of course, arr stores all of them 5 integer objects. It is array after
--all. Your example does not show it since ostream is not made to
--display whole arrays. ostream can display a void* and that is into
--what any array converts to as soon someone coughs at it (bloody legacy
--from C). But we can help ostream out easily to accept int arrays too.
--See:

--#include<iostream>

--/// Helping poor ostream to output int arrays
-- template<int N>
-- std::eek:stream& operator<<( std::eek:stream& o, int const (& a)[N] )
-- {
-- o<< "{";
-- for ( int i = 0; i< N; ++i )
-- {
-- o<< a;
-- if ( i< N-1 ) o<< ",";
-- }
-- o<< "}";
-- return o;
-- }
--
-- int main()
-- {
-- // Pauls code
-- int arr[5]={0};
-- std::cout<< "arr ="<< arr<< std::endl;
-- std::cout<< "arr[0] ="<< arr[0]<< std::endl;
-- // that is what arr converted to without our operator
-- std::cout<< "&arr[0] = "<< &arr[0]<< std::endl;
-- }

--The output is:

--arr = {0,0,0,0,0}
--arr[0] = 0
--&arr[0] = 0012FF50

-- arr is still array of 5 ints. Can't be Paul you are arguing even
--against that?

The problem is not just ostream operator<< , its every operator in the
C++
language.


Yes. Lot of smart people have felt that it is a problem and made
classes to wrap raw arrays so to get rid of it in C++. Usage of raw
arrays in real C++ production code is relatively low these days.
The identifier 'arr' is evaluated as an addresss in almost all
situations
except typeid and sizeof:
int* p= arr; //This works
int x = arr; //This does not work

The 'p = arr' works, thanks to implicit arr to&arr[0] conversion. My
template above does not accept 'p' as int array argument anymore since
it is a true raw pointer unlike 'arr'. 'p' goes to cout as usual
void*. The 'x = arr' should indeed not to work because assigning whole
array to single int does not make sense.
Also consider this :
template<typename T>
void foo(T t){
std::cout<< typeid(t).name();}

foo(arr);
Given a free choice arr is passed as a pointer and not a reference.

Yes. That is because C did not have references, so there were only two
ways to pass arrays in C (1) as pointer to first element (+ size as
separate argument) or (2) as member of struct. Both ways are indirect.
So the C designer's felt that writing '&arr[0]' everytime they needed
a pointer to first element of array too verbose syntax. C++ did not
change that because one of objectives of C++ is making migrating from
C to C++ as painless as possible and that is achieved by making most C
code to compile with C++ compiler.
The identifier 'arr' does not behave like identifiers to other objects
in
C++ it is somewhat special.
I can agree that it is a non modifiable array-type object. But it does
not
identify an array in the same sense that other objects' names identify
them,
it indirectly identifies the array, because it must be dereferenced to
access the array of objects that it identifies.

Yes, the pointer to what array implicitly converts (as it only can)
indirectly identifies the array. However array itself is located in
memory exactly where it's elements are, starting from first element.
Consider the code:

int arr[5]={0};
std::cout<< "&arr[0] = "<< &arr[0]<< std::endl;
std::cout<< "&arr = "<< &arr<< std::endl;

By language rules the address of first element of array and address of
array itself are same. So arr is object consisting of 5 ints and not a
separate pointer-like object (residing in memory elsewhere) that
points to the ints.


Well said Öö Tiib, just to make it absolutely clear if the following
assertion doesn't shut Paul up then there is no hope for him:

assert((void*)&arr[0] == (void*)&arr);

There is no special hidden object containing the address of the array as
this assertion proves.

There is no special hidden objects in arrays.
An array is simply a sequence of objects in memory.

A pointer to an array of integer objects is of type int*.
A pointer to a single array object, of the given type, is of type int
(*)[n].
A pointer to an array of arrays is also of type int(*)[n].


A pointer to an array of T's is of type T*.
A pointer of type T (*)[n] is not a direct pointer to an array of T's , it
points to an objectional representation of an array of Ts', not to the array
of T's directly.

A 2D array is an array of 1D arrays.
The pointer type T(*)[n] is a pointer to a 2D array , for example:

int arr[4][5];
int(*p)[5] = arr;


The term "array" means a sequence of objects. You cannot point to these
objects without actually pointing to them.
 

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

Forum statistics

Threads
474,142
Messages
2,570,819
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top