比如:
[C++] 纯文本查看 复制代码 int a[3] = {1,2,3};
a 是数组名,既是整个数组的首地址也是第一个元素的地址。那么 &a 表示什么?
可以用下面的语句打印比较:
[C++] 纯文本查看 复制代码 printf ("0x%x\n", a);
printf ("0x%x\n", &a);
比较打印出的结果可知道 a 和 &a 的值一样,也就是都表示数组的首地址。那么它们一样么?答案是否定的。
&a 是一个整个数组的指针!
看下面的例子:
[C++] 纯文本查看 复制代码 include <stdio.h>
int main()
{
int a[3] = {1,2,3};
int *p=(int *)(&a + 1);
printf("%d\n",p[-1]);
return (0);
}
运行输出:beyes@linux-y1br:~/C> ./temp
3 为什么输出的是 3 ?
首先,(&a + 1) 指向的是 a[2] 后的地址,所以 p[-1] 就指向了 3 。
为了进一步考察,可以将上面的数组改写成:
[C++] 纯文本查看 复制代码 int a[3][3] = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
.../*然后*/....
int *p = (int *)(&a + 1);
printf ("%d\n", p[-1]);
printf ("%d\n", p[-2]);
运行后,会看到两次打印的值分别为 9 和 8 。注意,上面的是一个二维数组,&a + 1 指向的是整个数组之后。
还可以继续看下面一个例子,下面的这个例子里,声明了三个一样大小的二维数组:
[C++] 纯文本查看 复制代码 int a[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int b[3][3] = {11, 12, 13, 14, 15, 16, 17, 18, 19};
int c[3][3] = {20, 21, 22, 23, 24, 25, 26, 27, 28};
int *p = (int *)(&a + 1);
printf ("%d\n", *p);
p = (int *)(&a + 2);
printf ("%d\n", *p);
上面打印输出分别为 11 和 20 。由此可见,&a 是一个指向 3x3 的二维数组指针,+1 就表示它一次移动 3x3 个 int 型数组的范围。上面需要注意的是,如果数组 b 和 c 不是声明为和 a 一样的 3x3 的二维数组,那么可能得不到期望的输出,这是因为编译器对不同类型的数组,在内存中可能不是以连续空间存放的(这里就涉及到一个内存对齐的问题)。 |