#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
有人可以解释我是怎么得到这个的吗?
答案 0 :(得分:7)
以下是a
,a+1
和&a+1
的每一项内容:
a
:由于a
是一个数组,因此使用a
会使其衰减成指向此数组的第一个元素的指针,该数组是一个包含4个整数的数组(类型因此,a
是int (*)[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+1
是a
+ 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