数组中元素的地址

时间:2014-01-17 11:58:10

标签: c multidimensional-array

#include<stdio.h>
int main()
{
   int a[3][4]={2,5,3,2,6,9,0,1,8,10,11,12};
   printf("%u, %u, %u",a,a+1,&a+1);
   return 0;
   getch();
}

此代码的输出为:

 2293472,  2293488, 2293520

有人可以解释我是怎么得到这个的吗?

3 个答案:

答案 0 :(得分:7)

以下是aa+1&a+1的每一项内容:

  • a:由于a是一个数组,因此使用a会使其衰减成指向此数组的第一个元素的指针,该数组是一个包含4个整数的数组(类型因此,aint (*)[4])。这是您要打印的地址:数组a的第一个元素的地址(也是第二级数组中第一个元素的地址)
  • a+1:这与选择a并将其移至下一个sizeof(int)*4个字节的对象相同,因为a的每个元素都是一个数组4个整数。因此,这将在a
  • 中打印第二个元素的地址
  • &a+1:这是少数例外情况,其中不应用数组到指针的确定规则。当数组是引用运算符(&)的操作数,sizeof的操作数或字符串文字初始值设定项时,数组不会衰减为指针。因此,&a不是指向4个整数数组的指针,而不是它,它是数组的地址,按照惯例,它是a中第一个元素的地址。地址与a相同(是的,a&a具有相同的地址),但区别在于&a具有指向数组的类型指针[3] [ int的4],即int (*)[3][4],意味着下一个对象(&a+1的结果)距离sizeof(int)*3*4个字节,这就是你得到的地址。

附注:您应该使用%p来打印指针值,而不是依赖于指针与unsigned int的大小相同的事实。这是正确的:

printf("%p, %p, %p", (void *) a, (void *) (a+1), (void *) (&a+1));

查看您获得的输出,我可以看到系统中sizeof(int)为4。通过一些小数学,你可以看到确实a+1a + 16(2293472 + 4 * 4 = 2293488),而&a+1是4 * 3 * 4字节; 2293472 + 4 * 3 * 4 = 2293520

答案 1 :(得分:2)

使用%u打印地址是未定义的行为,因此程序可以自由打印任何。在这种情况下,行为显然已由特定编译器实现,这就是它的作用:

  • a是数组本身,因此它打印分配2D数组的地址。显然是地址2293472d。
  • a+1表示由于a是算术表达式的一部分,它将衰减为指向其第一个元素的指针,而第一个元素又是一个包含4个元素的数组。 “array + 1”表示你取这个数组的地址+这样一个数组的大小。以字节为单位,表示您希望数组地址为4*sizeof(int)。换句话说,2293472d + 4 * 4 = 223488d。
  • &a+1表示您获得了一个指向整个数组的数组指针,然后通过一个完整数组的sizeof增加它。 2293472d + 3*4*sizeof(int) = 2293520。

理解这一点的关键是要了解数组指针数组指针之间的区别,它们有3种不同,但密切相关类型。 C FAQ比我更好地解释了这一点。链接到章节是所有C程序员,初学者和退伍军人都必须阅读的。

答案 2 :(得分:1)

嗯,这是继续......

您只打印a并且这是一个指针,显然会在输出屏幕上显示该地址的值。

接下来打印出a+1。 int数据类型的大小是4个字节。这里[0] [0]的地址是2293472。现在你要求的是一个+ 1的地址值,其中一个由4个整数组成。这需要4 * 4 = 16字节的内存。所以a + 1产生的a值增加到16,即2293488

接下来打印出&amp; a + 1。它给出的地址完全在分配给变量的区域之后(即这里的整数数组)。您的数组包含12个值,表示它需要48个字节的大小。所以你得到的输出是2293472 + 48 = 2293520