数组指向衰减并将multidimensional array传递给函数
我知道一个数组衰减到一个指针,如果一个声明
char things[8];
然后在其他地方使用的things
, things
是一个指向数组中的第一个元素的指针。
另外,从我的理解,如果一个声明
char moreThings[8][8];
那么moreThings
不是指向char的types指针,而是types“指向char的指针数组”,因为衰减只发生一次。
当更多的moreThings
传递给一个函数(比如用原型void doThings(char thingsGoHere[8][8])
来实现的时候,堆栈实际上是怎么回事?
如果moreThings
不是指针types,那么这真的还是一个通过引用? 我想我一直认为moreThings
仍然代表了multidimensional array的基地址。 如果doThings
把input的thingsGoHere
,它自己把它传递给另一个函数呢?
规则非常多,除非指定一个数组input为const
那么该数组将永远是可修改的?
我知道types检查的东西只发生在编译时,但我仍然困惑什么在技术上被视为通过引用传递(即只有当types指针的parameter passing,或指针数组是通过 – 通过引用以及?)
对不起,这个问题到处都是,但是由于我很难理解这个问题,所以很难说清楚一个确切的问题。
你有一点点错误: moreThings
也衰减到指向第一个元素的指针,但由于它是一个字符数组的数组,第一个元素是一个“8字符数组”。 所以腐烂的指针是这样的:
char (*p)[8] = moreThings;
指针的值当然与&moreThings[0][0]
的值相同,也就是第一个元素的第一个元素的值,同样也是&a
,但是types在每种情况下都是不同的。
下面是一个例子,如果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]
,与第一个元素的地址相同,它本身就是char[3]
-
&a[0][0]
:第一个元素的第一个元素的地址,它是一个char
这表明不同的对象可能具有相同的地址,但是如果两个对象具有相同的地址和相同的types,则它们是相同的对象。
“arrays地址和多维arrays指针”
让我们先从一维数组开始:
-
宣言
char a[8];
创build一个8个元素的数组。
这里a
元素的 地址,而不是数组的地址 。 -
char* ptr = a;
是正确的expression式,因为ptr
是指向char的指针,可以解决第一个元素。 -
但是expression式
ptr = &a
是错的 ! 因为ptr
无法寻址数组。 -
&数组的一个手段地址。 真正的
a
和&a
是相同的,但在语义上是不同的,一个是char的地址,另一个是8个字符的数组地址。 -
char (*ptr2)[8];
这里ptr2 is pointer to an array of 8 chars
,这次ptr2=&a
是一个有效的expression式。 -
&a
数据types是char(*)[8]
,而a
types是char[8]
,在大多数操作中简单地衰减到char*
,例如char* ptr = a;
要更好地理解阅读:
char *str
和char str[]
之间的区别以及如何在内存中存储?
第二种情况,
-
声明
char aa[8][8];
创build一个8x8
大小的二维数组。 -
任何二维数组也可以看作一维数组,其中每个数组元素是一维数组 。
-
aa
是第一个元素的地址,它是8个字符的数组。 expression式ptr2 = aa
是有效和正确的。 -
如果我们声明如下:
char (*ptr3)[8][8]; char ptr3 = &aa; //is a correct expression
同样的,
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]
。为了更好地理解: 当
str
被声明为char str[10]
时,&str
和str
之间的区别?
此外,
-
void doThings(char thingsGoHere[8][8])
只是voiddoThings(char (*thingsGoHere)[8])
,因此接受任何二维数组,而第二维为8。
关于C和C ++中的variablestypes:(我想添加回答)
- C ++ 中的C ++概念没有任何引用 。 如果它在C中使用,那就意味着作者在谈论指针variables。
- C支持
pass by Address
pass by value
。 -
C ++支持
Pass by address
,pass by value
pass by Reference
,也pass by Reference
。阅读: 指针variables和引用variables
最后,
- 名称数组是常量标识符不可变。
恰好Kerrek解释说,
除此之外,我们可以通过下面的例子来certificate:
#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大小是4个字节]
希望这可以帮助。 🙂