目录
指针
一级指针:
地址:一级指针自身的地址 数据:数据
二级指针:
地址:二级指针自身的地址 数据:一级指针的地址
三级指针:
地址:三级指针自身的地址 数据:二级指针的地址
数组
- 数组名就代表数组第一个元素的地址
-
sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,单位是字节。
-
&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)
一维数组:
例如下面这段代码
int a[] = {1,2,3,4,5};
printf("%p\n", &a[0]);
printf("%p\n", a);
printf("%zd\n", sizeof(a));
printf("%p\n", &a);
printf("%zd\n\n", sizeof(&a));
printf("%zd\n", sizeof(a[0]));
printf("%zd\n", sizeof(*(a + 0)));
printf("%zd\n", sizeof(&a[0]));
printf("%zd\n\n", sizeof(a + 0));
printf("%p\n", a);
printf("%p\n", a + 1);
printf("%p\n", &a + 1);
先看a、&a、&a[0]之间的关系
在上述代码中虽然a、&a、&a[0]所表示的地址都与首元素地址一致,但其类型并不一致,//因为地址其实就是指针所以每个变量的地址都有它的类型
使用调试功能可以看到
a代表整个数组,数据类型是int[5]
&a代表整个数组的地址,数据类型是int[5]*
&a[0]代表数组数组第一个元素的地址,数据类型是int*
由上面的分析不难想到
sizeof(a)得出的是整个数组所占的字节数
而sizeof(&a)得出的是一个指针变量所占的字节数(即int[5]*)
运行结果也验证了这一点
又因为a[i]=*(a+i)
所以自然就也有:
&a[i]=(a+i)
而i的取值范围也就可一看出来是0-max
根据上面的分析我们知道a+i和&a[i]是一样的所以a+i和&a[i]都是以一个数组元素进行加减地址的
而&a由于其数据类型是int[5]*所以它的地址加减是以一个数组的大小为单位的
0x4c-0x48=4 //数组元素的数据类型是int所占的字节数是4个字节
0x5c-0x48=20 //20/4==5//而数组中的元素个数也是5
二维数组:
二维数组虽然形态上相较一维数组多了一维但是本质上还是一维数组所以两者有着很多的共性
int a[][3] = { {1,2,3},{4,5,7} };
printf("%p\n", &a[0]);
printf("%p\n", a);
printf("%zd\n", sizeof(a));
printf("%p\n", &a);
printf("%zd\n\n", sizeof(&a));
printf("%p\n", &a[0][0]);
printf("%p\n", a[0]);
printf("%zd\n", sizeof(a[0]));
printf("%p\n", &a[0]);
printf("%zd\n\n", sizeof(&a[0]));
printf("%zd\n", sizeof(a[0]));
printf("%zd\n", sizeof(*(a + 0)));
printf("%zd\n", sizeof(&a[0]));
printf("%zd\n\n", sizeof(a + 0));
printf("%zd\n", sizeof(a[0][0]));
printf("%zd\n", sizeof(*(a[0] + 0)));
printf("%zd\n", sizeof(&a[0][0]));
printf("%zd\n\n", sizeof(a[0] + 0));
printf("%p\n", a);
printf("%p\n", a + 1);
printf("%p\n", &a[0] + 1);
printf("%p\n\n", &a + 1);
printf("%p\n", a[0]);
printf("%p\n", a[0] + 1);
printf("%p\n", &a[0][0] + 1);
printf("%p\n\n", &a[0] + 1);
依然是先看a、&a、&a[0]之间的关系
通过结果我们依然可以得到和一维数组相同的结论
即
a代表整个数组,数据类型是int[2][3]
&a代表整个数组的地址,数据类型是int[2][3]*
&a[0]代表数组数组第一个元素的地址,数据类型是int[3]*
当我们将维度下降一维结论同样成立
只不过a、&a、&a[0]分别被a[0]、&a[0]、&a[0][0]所代替,但他们功能完全相同即a[0]相对于a[0][0]就是数组名的存在,开头提到的&数组名和sizeof(数组名)等情况对于此时的a[0]也是同样适用的。
剩下的性质也和以上分析一样,就不赘述了。
指针运算笔试题
题目是这样的
#include <stdio.h>
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}
以下是我自己的解题思路
-------通过观看鹏哥C语言的课程后自行整理(视频链接见下方)