问题
I know that an array decays to a pointer, such that if one declared
char things[8];
and then later on used things
somewhere else, things
is a pointer to the first element in the array.
Also, from my understanding, if one declares
char moreThings[8][8];
then moreThings
is not of type pointer to char but of type \"array of pointers to char,\" because the decay only occurs once.
When moreThings
is passed to a function (say with prototype void doThings(char thingsGoHere[8][8])
what is actually going on with the stack?
If moreThings
is not of pointer type, then is this really still a pass-by-reference? I guess I always thought that moreThings
still represented the base address of the multidimensional array. What if doThings
took input thingsGoHere
and itself passed it to another function?
Is the rule pretty much that unless one specifies an array input as const
then the array will always be modifiable?
I know that the type checking stuff only happens at compile time, but I\'m still confused about what technically counts as a pass by reference (i.e. is it only when arguments of type pointer are passed, or would array of pointers be a pass-by-reference as well?)
Sorry to be a little all over the place with this question, but because of my difficulty in understanding this it is hard to articulate a precise inquiry.
回答1:
You got it slightly wrong: moreThings
also decays to a pointer to the first element, but since it is an array of an array of chars, the first element is an "array of 8 chars". So the decayed pointer is of this type:
char (*p)[8] = moreThings;
The value of the pointer is of course the same as the value of &moreThings[0][0]
, i.e. of the first element of the first element, and also the same of &a
, but the type is a different one in each case.
Here's an example if char a[N][3]
:
+===========================+===========================+====
|+--------+--------+-------+|+--------+--------+-------+|
|| a[0,0] | a[0,1] | a[0,2]||| a[1,0] | a[1,1] | a[1,2]|| ...
|+--------+--------+-------+++--------+--------+-------++ ...
| a[0] | a[1] |
+===========================+===========================+====
a
^^^
||+-- &a[0,0]
|+-----&a[0]
+-------&a
&a
: address of the entire array of arrays of chars, which is achar[N][3]
&a[0]
, same asa
: address of the first element, which is itself achar[3]
&a[0][0]
: address of the first element of the first element, which is achar
This demonstrates that different objects may have the same address, but if two objects have the same address and the same type, then they are the same object.
回答2:
"ARRAY ADDRESS AND POINTERS TO MULTIDIMENSIONAL ARRAYS"
Lets we start with 1-D array first:
Declaration
char a[8];
creates an array of 8 elements.
And herea
is address of fist element but not address of array.char* ptr = a;
is correct expression asptr
is pointer to char and can address first element.But the expression
ptr = &a
is wrong! Becauseptr
can't address an array.&a means address of array. Really Value of
a
and&a
are same but semantically both are different, One is address of char other is address of array of 8 chars.char (*ptr2)[8];
Hereptr2 is pointer to an array of 8 chars
, And this timeptr2=&a
is a valid expression.Data-type of
&a
ischar(*)[8]
and type ofa
ischar[8]
that simply decays intochar*
in most operation e.g.char* ptr = a;
To understand better read: Difference between char *str and char str[] and how both stores in memory?
Second case,
Declaration
char aa[8][8];
creates a 2-D array of8x8
size.Any 2-D array can also be viewed as 1-D array in which each array element is a 1-D array.
aa
is address of first element that is an array of 8 chars. Expressionptr2 = aa
is valid and correct.If we declare as follows:
char (*ptr3)[8][8]; char ptr3 = &aa; //is a correct expression
Similarly,
moreThings
in your declarationchar moreThings[8][8];
contain address of fist element that is char array of 8 elements.To understand better read: Difference between char* str[] and char str[][] and how both stores in memory?
It would be interesting to know:
morething
is an address of 8 char array .*morething
is an address of first element that is&morething[0][0]
.&morething
is an address of 2-D array of 8 x 8.And address values of all above three are same but semantically all different.
**morething
is value of first element that ismorething[0][0]
.To understand better read: Difference between &str and str, when str is declared as char str[10]?
Further more,
void doThings(char thingsGoHere[8][8])
is nothing but voiddoThings(char (*thingsGoHere)[8])
and thus accepts any array that is two dimensional with the second dimension being 8.
About type of variables in C and C++: (I would like to add in answer)
- Nothing is pass by reference in C its C++ concept. If its used in C that means author talking about pointer variable.
- C supports
pass by Address
andpass by value
. C++ supports
Pass by address
,pass by value
and alsopass by Reference
.Read: pointer variables and reference variables
At the end,
- Name Of an array is constant identifier not variable.
回答3:
Nicely explained by Kerrek,
In addition to that, we can prove it by the following example:
#include <stdio.h>
int main ()
{
int a[10][10];
printf (".. %p %p\n", &a, &a+1);
printf (".. %p %p \n ", &a[0], &a[0]+1);
printf (".. %p %p \n ", &a[0][0], &a[0][0] +1);
}
The Output is :
.. 0x7fff6ae2ca5c 0x7fff6ae2cbec = 400 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca84 = 40 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca60 = 4 bytes difference.
&a +1 -> Moves the pointer by adding whole array size. ie: 400 bytes
&a[0] + 1 -> Moves the pointer by adding the size of column. ie: 40 bytes.
&a[0][0] +1 -> Moves the pointer by adding the size of element ie: 4 bytes.
[ int size is 4 bytes ]
Hope this helps. :)
来源:https://stackoverflow.com/questions/12674094/array-to-pointer-decay-and-passing-multidimensional-arrays-to-functions