我知道数组会衰减到指针,如果声明了
char things[8];
然后在其他地方使用things
,things
是指向数组中第一个元素的指针。
另外,根据我的理解,如果有人宣布
char moreThings[8][8];
然后moreThings
不是类型指向char的类型,但类型为“指向char的指针数组”,因为衰减只发生一次。
当moreThings
被传递给一个函数时(比如原型void doThings(char thingsGoHere[8][8])
,堆栈实际上发生了什么?
如果moreThings
不是指针类型,那么这仍然是一个传递参考吗?我想我一直认为moreThings
仍然代表多维数组的基地址。如果doThings
接受输入thingsGoHere
并将其传递给另一个函数,该怎么办?
规则几乎是除非将数组输入指定为const
,否则数组将始终可修改?
我知道类型检查的东西只发生在编译时,但是我仍然对技术上作为引用传递的东西感到困惑(即只有当传递类型指针的参数时,或者指针数组是也是一个传递参考?)
很抱歉有这个问题的所有地方,但由于我很难理解这一点,很难说出一个精确的询问。
答案 0 :(得分:22)
你有点错误:moreThings
也衰减到指向第一个元素的指针,但由于它是一个字符数组的数组,第一个元素是“8个字符数组”。所以腐朽的指针属于这种类型:
char (*p)[8] = moreThings;
指针的值当然与&moreThings[0][0]
的值相同,即第一个元素的第一个元素的值,也是&a
的相同值,但类型在每种情况下都是不同的。
以下是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
:整个字符数组数组的地址,char[N][3]
&a[0]
,与a
相同:第一个元素的地址,本身就是char[3]
&a[0][0]
:第一个元素的第一个元素的地址,即char
这表明不同的对象可能具有相同的地址,但如果两个对象具有相同的地址和,则它们是同一个对象。
答案 1 :(得分:13)
让我们先从1-D阵列开始:
声明char a[8];
创建一个包含8个元素的数组
此处a
是第一元素的地址,但不是数组的地址。
char* ptr = a;
是正确的表达式,因为ptr
是指向char的指针,可以解决第一个元素。
但表达式ptr = &a
错误!因为ptr
无法处理数组。
& a表示数组的地址。 a
和&a
的实际值相同,但语义上两者都不同,一个是char的地址其他是8个字符数组的地址。
char (*ptr2)[8];
此处ptr2 is pointer to an array of 8 chars
,这一次
ptr2=&a
是一个有效的表达方式。
&a
的数据类型为char(*)[8]
,a
的类型为char[8]
,在大多数操作中只会衰减为char*
,例如char* ptr = a;
char aa[8][8];
要理解更好的阅读:Difference between char *str
and char str[]
and how both stores in memory?
第二种情况,
声明8x8
会创建一个aa
大小的二维数组。
任何二维数组也可以视为一维数组,其中每个数组元素都是一维数组。
ptr2 = aa
是第一个元素的地址,它是一个包含8个字符的数组。表达式char (*ptr3)[8][8];
char ptr3 = &aa; //is a correct expression
有效且正确。
如果我们声明如下:
moreThings
<强>类似地,强>
声明char moreThings[8][8];
中的morething
包含第一个元素的地址,该元素是8个元素的char数组。
要理解更好的阅读:Difference between char* str[]
and char str[][]
and how both stores in memory?
知道:
会很有趣 *morething
是8个字符数组的地址。
&morething[0][0]
是第一个元素&morething
的地址。
**morething
是8 x 8的二维数组的地址。
以上三者的地址值相同但在语义上都不同。
morething[0][0]
是void doThings(char thingsGoHere[8][8])
的第一个元素的值。
要理解更好的阅读:Difference between &str
and str
, when str
is declared as char str[10]
?
此外,
doThings(char (*thingsGoHere)[8])
只是空pass by Address
,因此接受任何二维数组,第二维为8。关于C和C ++中的变量类型:(我想在答案中添加)
pass by value
和Pass by address
。 C ++支持pass by value
,pass by Reference
以及{{1}}。
最后,
答案 2 :(得分:4)
Kerrek很好地解释,
除此之外,我们可以通过以下示例证明:
#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);
}
输出是:
.. 0x7fff6ae2ca5c 0x7fff6ae2cbec = 400 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca84 = 40 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca60 = 4 bytes difference.
&amp; a +1 - &gt;通过添加整个数组大小来移动指针。即:400字节
&amp; a [0] + 1 - &gt;通过添加列的大小来移动指针。即:40个字节。
&amp; a [0] [0] +1 - &gt;通过添加元素的大小来移动指针,即:4个字节。
[int size is 4 bytes]
希望这会有所帮助。 :)