lla*_*ais 10 c arrays callstack pointers multidimensional-array
我知道一个数组衰减到指针,如果一个声明
char things[8];
Run Code Online (Sandbox Code Playgroud)
然后在things其他地方使用,things是一个指向数组中第一个元素的指针.
另外,根据我的理解,如果有人宣称
char moreThings[8][8];
Run Code Online (Sandbox Code Playgroud)
那么moreThings它不是指向char的类型指针,而是类型为"指向char的指针数组",因为衰减只发生一次.
什么时候moreThings传递给一个函数(比如说原型void doThings(char thingsGoHere[8][8])实际上是什么进行了堆栈?
如果moreThings不是指针类型,那么这仍然是一个传递引用?我想我一直认为它moreThings仍然代表了多维数组的基地址.如果doThings接受输入thingsGoHere并将其传递给另一个函数会怎么样?
规则几乎是除非指定数组输入,const然后数组将始终可修改?
我知道类型检查的东西只发生在编译时,但我仍然对技术上作为一个引用传递的东西感到困惑(即只有当传递类型指针的参数时,或者指针数组是否为传递 - 参考也是?)
很抱歉这个问题在这个地方有点儿,但由于我很难理解这一点,很难说出一个精确的询问.
Ker*_* SB 22
你有点错误:moreThings也衰减到指向第一个元素的指针,但由于它是一个字符数组的数组,第一个元素是"8个字符数组".所以腐朽的指针属于这种类型:
char (*p)[8] = moreThings;
Run Code Online (Sandbox Code Playgroud)
指针的值当然与&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
Run Code Online (Sandbox Code Playgroud)
&a:字符数组的整个数组的地址,这是一个 char[N][3]
&a[0],同样如下a:第一个元素的地址,它本身就是一个char[3]
&a[0][0]:第一个元素的第一个元素的地址,即a char
这表明不同的对象可能具有相同的地址,但如果两个对象具有相同的地址和相同的类型,则它们是相同的对象.
Gri*_*han 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 *str和char str[]记忆,如何既店?
第二种情况,
声明char aa[8][8];创建一个8x8大小的二维数组.
任何2-D阵列也可以被视为1-D阵列,其中每个阵列元素是1-D阵列.
aa是第一个元素的地址,是8个字符的数组.表达ptr2 = aa是有效和正确的.
如果我们声明如下:
char (*ptr3)[8][8];
char ptr3 = &aa; //is a correct expression
Run Code Online (Sandbox Code Playgroud)
同样,
moreThings在您的声明中char moreThings[8][8];包含第一个元素的地址,即8个元素的char数组.
为了更好地理解阅读:区别char* str[]和char str[][]记忆,如何既店?
知道这将是有趣的:
morething 是一个8字符数组的地址.
*morething是第一个元素的地址&morething[0][0].
&morething 是8 x 8的二维数组的地址.
并且所有上述三个的地址值相同但在语义上都是不同的.
**morething是第一个元素的值morething[0][0].
要理解更好的阅读:和之间的区别,何时被宣布为?&strstrstrchar str[10]
更进一步,
void doThings(char thingsGoHere[8][8])只是空虚doThings(char (*thingsGoHere)[8]),因此接受任何二维数组,第二维为8.关于C和C++中的变量类型:(我想在答案中添加)
pass by Address和pass by value.C++支持Pass by address,pass by value也是pass by Reference.
在末尾,
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);
}
Run Code Online (Sandbox Code Playgroud)
输出是:
.. 0x7fff6ae2ca5c 0x7fff6ae2cbec = 400 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca84 = 40 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca60 = 4 bytes difference.
Run Code Online (Sandbox Code Playgroud)
&a +1 -> 通过添加整个数组大小来移动指针。即:400 字节
&a[0] + 1 -> 通过增加列的大小来移动指针。即:40 个字节。
&a[0][0] +1 -> 通过添加元素的大小来移动指针,即:4 个字节。
[整数大小为 4 个字节]
希望这可以帮助。:)