#include <stdio.h>
int main()
{
int a[2][3] = {
2, 4, 6,
8, 10, 12};
printf("a:%p, a+1:%p\n", a, a + 1); // 相差3*sizeof(int)=12,二维数组名是一个指向每一行的指针,a:0061FF08, a+1:0061FF14
printf("&a:%p, &a+1:%p\n", &a, &a + 1); // 相差6*sizeof(int)=1224,&a:0061FF08, &a+1:0061FF20
printf("a[0]:%p, a[0]+1:%p\n", a[0], a[0] + 1); // 相差一个sizeof(int)也就是一个数更多v组元素,a[0]:0061FF08, a[0]+1:0061FF0C
printf("&a[0]:%p, &a:%p\n", &a[0], &a); // 结果一样,&a[0]:0061FF08, &a:0061FF08
printf("&a[0]+1:%p, &a+1:%p\n", &a[0] + 1, &a + 1); //&a[0]跳了12个字节(跳过了一行),而&a跳了24个字节(跳过了整个二维数组)
printf("*a:%p, *a+1:%p,*(a+1):%p\n", *a, *a + 1, *(a + 1)); /* a:0061FF08, *a+1:0061FF0C,*(a+1):0061FF14
*a+1偏移了一个sizeof(int).*(a+1)偏移了一行 */
printf("**a:%p, **a+1:%p,**(a+1):%p\n", **a, **a + 1, **(a + 1));
printf("*a[0]:%p, *a[0]+1:%p,*(a[0]+1):%p\n", *a[0], *a[0] + 1, *(a[0] + 1));
printf("*a[1]:%p, *a[1]+1:%p,*(a[1]+1):%p\n", *a[1], *a[1] + 1, *(a[1] + 1));
}
-
printf("a:%p, a+1:%p\n", a, a + 1);
输出结果:
a:0061FF08, a+1:0061FF14
解释:a
是指向二维数组第一行的指针,a+1
是指向二维数组第二行的指针。每行有3个int
元素,所以相差3个sizeof(int)
字节,即12个字节。 -
printf("&a:%p, &a+1:%p\n", &a, &a+1);
输出结果:
&a:0061FF08, &a+1:0061FF20
解释:&a
是整个二维数组的地址,&a+1
是整个二维数组后面的地址。整个二维数组占用了2行3列,总共有6个int
元素,所以相差6个sizeof(int)
字节,即24个字节。 -
printf("a[0]:%p, a[0]+1:%p\n", a[0], a[0]+1);
输出结果:
a[0]:0061FF08, a[0]+1:0061FF0C
解释:a[0]
是二维数组的第一行,是指向第一个元素的指针。每个元素占用一个sizeof(int)
字节,所以相差一个sizeof(int)
字节。 -
printf("&a[0]:%p, &a:%p\n",&a[0], &a);
输出结果:
&a[0]:0061FF08, &a:0061FF08
解释:&a[0]
是二维数组的第一行的地址,与&a
相同,都是指向二维数组第一行的指针。 -
printf("&a[0]+1:%p, &a+1:%p\n",&a[0]+1, &a+1);
输出结果:
&a[0]+1:0061FF14, &a+1:0061FF20
解释:&a[0]+1
跳过了一行,相当于指向了第二行的地址;&a+1
跳过了整个二维数组,指向了整个二维数组后面的地址。 -
printf("*a:%p, *a+1:%p,*(a+1):%p\n",*a, *a+1,*(a+1));
输出结果:
*a:0061FF08, *a+1:0061FF0C,*(a+1):0061FF14
解释:*a
是指向第一行的指针,解引用后得到第一行的第一个元素;*a+1
偏移了一个sizeof(int)
字节,即指向第一行的第二个元素;*(a+1)
是指向第二行的指针,解引用后得到第二行的第一个元素。 -
printf("**a:%p, **a+1:%p,**(a+1):%p\n",**a, **a+1,**(a+1));
输出结果:
**a:00000002, **a+1:00000003,**(a+1):00000008
解释:**a
是指向第一行的指针,解引用两次后得到第一行的第一个元素;**a+1
对第一行的第一个元素加1;**(a+1)
是指向第二行的指针,解引用两次后得到第二行的第一个元素。 -
printf("*a[0]:%p, *a[0]+1:%p,*(a[0]+1):%p\n",*a[0], *a[0]+1,*(a[0]+1));
输出结果:
*a[0]:00000002, *a[0]+1:00000003,*(a[0]+1):00000004
解释:*a[0]
是第一行的第一个元素,解引用后得到该元素的值;*a[0]+1
加上1;*(a[0]+1)
是第一行的第二个元素,解引用后得到该元素的值。 -
printf("*a[1]:%p, *a[1]+1:%p,*(a[1]+1):%p\n",*a[1], *a[1]+1,*(a[1]+1));
输出结果:
*a[1]:00000008, *a[1]+1:00000009,*(a[1]+1):0000000A
解释:*a[1]
是第二行的第一个元素,解引用后得到该元素的值;*a[1]+1
加上1;*(a[1]+1)
是第二行的第二个元素,解引用后得到该元素的值。
涉及到了指针和数组的相关知识点,以下是一些总结:
-
指针与地址:指针是存储内存地址的变量,可以通过加/减整数来进行地址运算。
&
运算符用于获取一个变量的地址。 -
数组与指针:数组名可以看作是指向数组第一个元素的指针。对于二维数组,每一行都可以看作是指向该行第一个元素的指针。使用
a[i]
或*(a+i)
来访问数组元素。 -
指针运算:指针运算的结果取决于指针类型和操作数的类型。对指针进行加/减操作时,会根据指针所指向类型的大小进行相应的偏移。
-
解引用操作符:使用
*
运算符可以解引用指针,获取指针所指向的值。 -
printf格式化输出:
%p
用于打印指针地址的值。
二维数组名是指向行的,“&二维数组名”就指向了整个二维数组,"二维数组名[i]" 是指向i行的首元素的地址·。“&二维数组名[i]”就指向了一行。
在C语言中,数组名是一个指向数组第一个元素的指针,即其本身代表了该数组第一个元素的地址。因此,在使用数组名时,可以将其视为指向数组第一个元素的指针,例如a[i]
就是指向二维数组第i
行第一个元素的指针。
对于二维数组而言,&a[i]
表示的是二维数组的第i
行的地址,但由于数组名已经代表了该数组第一个元素的地址,所以a[i]
和&a[i]
其实是等价的,它们所代表的值也相同。
*二维数组名[i]就是取出第i行首元素的值,
*二维数组名[i]+1就是对取出第i行首元素的值进行+1,
*(二维数组名[i]+1)就是对取出第i+1行首元素的值进行+1