Paul said:
An array object is not the same as a single variable.
Well - this is likely a mistake.. but....
Let me say that appreciate your zeal in defending your understanding.
Let's start with some pretty basic principles.
First - to offer my credentials... I've actually implemented C and C++
compilers,
we have one of the premier offerings for the mainframe (z/Architecture)
system.
So, I speak with some authority (BTDT.)
In my discussions below, I am trying to be clear, but if I'm not, let
me apoligize
a-priori... if I am unclear, please feel free to ask...
So - to begin with some basic principles; let's remove the complications
of templates, function overloading, etc... and let's just talk
about some really simple/straight-forward examples and how things
actually work "under the covers" for those simple situations.
An array is a sequence of objects that cannot be addressed with a
single instruction, unless its size one or soemthing silly.
An object of array type is an object that strores the pointer to the
array , for example arr in the following:
int arr[5];
Hmm... those sound like nice definitions... but, I think I would prefer
some simpler ones. I'm terribly confused by this "object of array type"
you have there, and why you would need one...
So - let me offer these...
Let's say that an array is a contiguous sequence of elements.
Arrays may be indexed, which results in a single element. (Let's not get
into multi-dimension issues for the moment; just one dimension.) An array
defines the number of elements it comprises, starting at element #0 and
continuing to n-1 elements.
Does that sound good?
If so - let's continue with this example:
int arr[5];
If we agree on the basic definition, then this would indicate that,
somewhere at runtime, there is a contiguous set of 5 'int' elements.
The name of that contigous set of elements is 'arr'.
Does that sound good?
So - then, expanding further... using our definition above, let's
consider this snippet:
int i;
int arr[5];
i = arr[4];
What are the basic semantics of that? I propose that would mean
to find the location of the array name 'arr', treat this as a pointer to
the first element of the array (per the rule), add to that starting
address 4*sizeof(int), to compute the address of the 4th element.
Dereference that point to access the `int' value located there,
then assign that `int' value to the variable 'i'.
Does that sound good/proper... is there something not right there?
(albeit, perhaps I'm a little loose, but I'm avoiding specifics like
'registers' and 'memory'.)
Now, let's consider this snippet:
int i;
int arr[5];
i = *((&arr[0]) + 4);
What does that statement do?
Following the indexing example we just walked thru, I propose
that it would mean, find the address of 'arr', treat it as a pointer to
the first element (per the rule), add 0*sizeof(int) to that pointer
to compute the address of the 0th element. Apply the '&' operator
which results in that same address. At this point, we have an (int *)
pointer to the 0th element. Add 4*sizeof(int) to it; which happens to
produce a pointer to the 4th element of the array. Apply the '*' operator
to dereference that point, which produces an `int' that is the 4th
element of the array. Assign that value to `i'.
Does that sound right?
I believe that would show, in this basic situation; the equivalence
of the two statements.
If you agree with that; then we have a very simple answer to this
statement:
output arr and you will find it has a pointer value.
Yes! That is true (again, neglecting templates and other more complicated
type situations.) I think, the reason it is true is because the
expression 'arr'
becomes a pointer to the first element of the array... hence, it,
definitionally
is a pointer value.
examine arr with typeid and you will find it is an array type.
OK - at this point - let's bring typeid back into the picture.
You are correct; it _is_ an array type... so - why does typeid() not say
it's a pointer??? I just got thru explaining why it would be a pointer,
but typeid() says it's not! What's going on?
This is because of the semantics of typeid(). My statements/rationing
above was discussing accessing the array... not examining its type.
typeid() only looks at the type... the type of 'arr' is the contigous set
of 5 elements... recall that typeid() doesn't evaluate the expression, it
evaluates the type of the expression... it's an important distinction.
examine with sizeof and you get the size of the whole array
The reason for this is the same as typeid(), sizeof() deals in the type
of the expression - it does not evaluate it.
arr is a non modifiable object that decays in a pointer. The pointer
value(the address of the array) is stored someplace so that when the
program is exectued the location of an element can be accessed for
example:
I'm not sure about the 'non-modifiable' part of that...
Clearly though, when you say "the pointer value.. is stored
someplace"... that is
frequently true... in this example:
void foo(int* p){
p[2] = 6;
}
If foo() were invoked with 'arr' as a parameter; then the address of
'arr' must
be stored somewhere... it's clearly stored in 'p'.
However, I believe the question really is "is it stored somewhere
else?" That is,
is there another "object" that contains the address of 'arr'.. and the
value
of the other object would be passed to foo()?
I think the answer is "well, you _could_ do it that way - but - it's
frequently
not needed."
Let's consider this for example:
int *ip;
int arr[5];
ip = arr;
foo(ip);
Would you say that would be equivalent to:
int arr[5];
foo(arr);
If so, then in the first case, clearly the pointer to the first element
of `arr'
has been saved in the "object" named `ip'. That value is then passed
as a parameter to foo().
In the second case, is there some mysterious unnamed "object" which
contains the address of the first element of `arr', and the value
of the unnamed "object" is then passed as a parameter to foo()?
Well - as an implementation detail; you _could_ do that... but it is more
likely that the compiler can generate code that computes the address
of `arr' and simply passes that computed value as the parameter to foo()?
Thus, if my assertion is correct the expression:
foo(arr)
actually can be thought to be equivalent to
foo((&arr[0]))
(again, neglecting templates/function-overloading, etc... let's keep it
simple.)
The second expression simply makes the underlying semantics obvious.
Got nothing to do with hardware registers really. Its more to do with
terminology and peoples understanding.
You are correct - I was using 'registers' as a term that I was hoping would
make things clear; I hope the discussion above (which avoids that) is more
in-line with what you are looking for.
A non modifiable object of array type, is not the same thing as an
array of integer objects that this object references.
I'm having problems with this sentence.. when you say "A non
modifiable object
of array type"; do you mean a `const' array ? I'm not sure I
understand what you're
getting at there...
Are you saying there exists this unnamed "object" that contains the
pointer to
array?
Although an array is not a pointer in C++. For the sake of this
discussion an array can be seen as basically a pointer to the first
element because in most situations it decays into a pointer.
I think this is an oversimplication; as you point out above... If we
agree
that an array is a contiguous set of elements, then that's what it is...
We then say that there is this added rule that when the array name is
referenced
in an expression, the result of that expression is a pointer to the
first element...
With those two, one can readily define the []-operator in a consistent
fashion
vis-a-vis pointer addition.
That is (and, again, this is neglecting templates/function-overloading,
etc...)
given these declarations:
int i;
int arr[5];
the statements:
i = arr[4];
and
i = *((&arr[0])+4);
are completely equivalent.
If we can agree on those definitions and these basic semantics, then we can
proceed to talk about the slightly-more-complicated issues, in particular,
how do you handle multiple dimensions, and what does "&arr" mean?
However, one step at a time.
- Dave Rivers -