是C ++中第一个元素地址的二维数组地址的名称吗?

时间:2015-03-23 19:58:13

标签: c++ arrays

实现这样的二维数组时:     int a[3][3]; 这些持有:A=&A[0],同时A[0]=&A[0][0]。所以,A=&(&A[0][0]),基本上说A是数组第一个元素地址的地址,这不是真的。这里我的错误是什么? A真的会衰减到指针的指针吗?

2 个答案:

答案 0 :(得分:1)

您的错误在于您对数组和指针之间的关系有不正确的理解。数组不是指针。这是一个数组。但是,数组 可以隐式转换为指向其自己的第一个元素的指针。所以,虽然这个表达式确实评估为true:

A == &A[0]

A &A[0]是不正确的。转换不会在所有表达式中发生。例如:

&A

这不会取A的第一个元素的地址(甚至没有意义)。它需要A的实际地址,其类型为int[3][3]。所以&A的类型是int(*)[3][3],读作“指向3个3个数组的数组的指针”。

&A&A[0]之间的主要区别在于,如果您向&A添加1,您将获得3 * 3 * sizeof(int)字节之外的地址,而如果您添加1到&A[0],你会得到一个只有3 * sizeof(int)字节的指针。

考虑到这一切,你应该能够看到你的错误所在。 A[0] &A[0][0],但它可以隐式转换为它。但是,与所有转换一样,这会产生一个临时的,您无法获取该地址。所以表达式&(&A[0][0])甚至没有意义。

答案 1 :(得分:0)

由于对我之前回答的反应,我做了一些研究,以便在我的解释中了解更多错误。 在这里找到了一个相当精细的主题解释:

http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c

我会试着总结一下:

如果您有以下内容:

char array_place[100] = "don't panic";
char* ptr_place = "don't panic";

在内存中表示它的方式完全不同。 而ptr_place是一个真正的指针,array_place只是一个标签。

char a = array_place[7];
char b = ptr_place[7];

C中数组的语义规定数组名是数组第一个元素的地址,这与说它是指针不同。因此在赋值给a,数组的第8个字符是通过将array_place的值偏移7来实现的,并将结果地址指向的内容移动到al寄存器中,然后移入a。

指针的语义完全不同。指针只是一个常规变量,碰巧将另一个变量的地址保存在里面。因此,为了实际计算字符串的第8个字符的偏移量,CPU将首先将指针的值复制到寄存器中,然后再将其递增。这需要另一条指令[1]。

实际上并没有破解编译器的程序员经常会忽略这一点。 C中的变量只是内存位置的方便的字母数字假名。如果我们编写汇编代码,我们只需在某个内存位置创建一个标签,然后访问此标签,而不是始终对内存值进行硬编码 - 这就是编译器的作用。

嗯,实际上由于加载和重定位问题,地址没有以绝对方式进行硬编码,但为了讨论起见,我们不必深入了解这些细节。

标签是编译器在编译时分配的东西。从这里可以看出数组和指针之间的巨大差异。 这也解释了为什么sizeof(array_place)给出了数组的完整大小,其中指针的大小将给出指针的大小。

我必须说,我自己并没有意识到这些微妙的差异,而且我在C和C ++以及数组中也已经编写了很长时间。

然而,如果数组元素的名称是数组的第一个元素的地址。您可以创建一个指针并将其初始化为该值

char* p = array_place

p将指向字符所在的内存位置。

总结:

必须牢记数组名称和指针之间的一个区别。指针是一个变量,因此p = array_place和p ++是合法的。但是数组名称不是变量;像array_place = p和array_place ++这样的结构是非法的。我知道的; - )