[英]Array to pointer decay and passing multidimensional arrays to functions
我知道一个数组衰减到指针,如果一个声明
char things[8];
然后在其他地方使用的things
, things
是指向数组中第一个元素的指针。
另外,根据我的理解,如果有人宣称
char moreThings[8][8];
那么moreThings
不是指向char的类型指针,而是类型为“指向char的指针数组”,因为衰减只发生一次。
当moreThings
传递给一个函数时(比如使用原型void doThings(char thingsGoHere[8][8])
,堆栈实际上会发生什么?
如果moreThings
不是指针类型,那么这仍然是一个传递参考吗? 我想我总是认为moreThings
仍然代表了多维数组的基地址。 如果doThings
接受输入thingsGoHere
并将其传递给另一个函数怎么办?
规则几乎是除非将数组输入指定为const
,否则数组将始终可修改?
我知道类型检查的东西只发生在编译时,但我仍然对技术上作为一个引用传递的东西感到困惑(即只有当传递类型指针的参数时,或者指针数组是否为传递 - 参考也是?)
很抱歉这个问题在这个地方有点儿,但由于我很难理解这一点,很难说出一个精确的询问。
你有点错误: moreThings
也衰减到指向第一个元素的指针,但由于它是一个chars数组的数组,第一个元素是“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-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
同样的,
moreThings
在声明char moreThings[8][8];
包含8个元素的char数组的第一个元素的地址。
知道这将是有趣的:
morething
是8个char数组的地址。
*morething
是第一个元素的地址,它是&morething[0][0]
。
&morething
是8 x 8的二维数组的地址。
并且所有上述三个的地址值相同但在语义上都是不同的。
**morething
是第一个元素的价值,更多的东西morething[0][0]
。
要理解更好的读取: 当str
被声明为char str[10]
时, &str
和str
之间的区别?
更进一步,
void doThings(char thingsGoHere[8][8])
只是void 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);
}
输出是:
.. 0x7fff6ae2ca5c 0x7fff6ae2cbec = 400 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca84 = 40 bytes difference
.. 0x7fff6ae2ca5c 0x7fff6ae2ca60 = 4 bytes difference.
&a +1 - >通过添加整个数组大小来移动指针。 即:400字节
&a [0] + 1 - >通过添加列的大小来移动指针。 即:40个字节。
&a [0] [0] +1 - >通过添加元素的大小来移动指针,即:4个字节。
[int size是4个字节]
希望这可以帮助。 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.