繁体   English   中英

数组指针衰减并将多维数组传递给函数

[英]Array to pointer decay and passing multidimensional arrays to functions

我知道一个数组衰减到指针,如果一个声明

char things[8];

然后在其他地方使用的thingsthings是指向数组中第一个元素的指针。

另外,根据我的理解,如果有人宣称

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是一个有效的表达式。

  • 数据类型&achar(*)[8]a类型是char[8] ,它在大多数操作中简单地衰减为char* ,例如char* ptr = a;

    要理解更好的读取: char *strchar 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数组的第一个元素的地址。

    要理解更好的读取: char* str[]char str[][]之间的区别以及两者如何存储在内存中?


知道这将是有趣的:

  • morething是8个char数组的地址。

  • *morething是第一个元素的地址,它是&morething[0][0]

  • &morething是8 x 8的二维数组的地址。

    并且所有上述三个的地址值相同但在语义上都是不同的。

  • **morething是第一个元素的价值,更多的东西morething[0][0]

    要理解更好的读取: str被声明为char str[10]时, &strstr之间的区别?

更进一步,

  • void doThings(char thingsGoHere[8][8])只是void doThings(char (*thingsGoHere)[8]) ,因此接受任何二维数组,第二维为8。

关于C和C ++中的变量类型:(我想在答案中添加)

  • 在C C ++概念中, 没有任何东西可以通过引用传递 如果它在C中使用,则表示作者在谈论指针变量。
  • C支持pass by Addresspass by value
  • C ++支持Pass by addresspass 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM