C|【C语言的灵魂】-指针(2)

目录

指针的运算
指针+-整数
指针-指针
用指针-指针的方法实现strlen函数
指针和数组
二级指针
指针数组
数组指针

指针的运算
指针+-整数
指针+-整数 就是对内存访问的时候应该跳过多少个字节,在之前已经介绍过来,这里就不说了
指针(1)
指针-指针
这个东西在数组中是很常见的,指针-指针 表示的是两个指针之间元素的个数
C|【C语言的灵魂】-指针(2)
文章图片

就像这样,低地址- 高地址,就会变成负的.
用指针-指针的方法实现strlen函数
#include #include int my_strlen(const char* str) { assert(str); //判断指针是否错误 char* tmp = str; while (*++tmp) { ; } return tmp - str; }

我还写了很多库函数的实现,大家有时间可以看看:各种库函数的实现
指针和数组
C|【C语言的灵魂】-指针(2)
文章图片


从调试中可以看出: 数组名和数组首元素的地址是一样的
所以: 数组名表示的是数组首元素的地址。
2种情况除外
1.sizeof(arr)此时的数组名代表整个数组,即单独放在sizeof中的数组名代表整个数组
2.&arr这是的数组名也代表整个数组,取出的是整个数组的地址
既然可以把数组名当成地址存放到一个指针中,那么我们使用指针来访问数组中的每一个元素.
int main() { int arr[] = { 0,1,2,3,4 }; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); int i = 0; for (i = 0; i < sz; i++) { printf("&arr[%d] = %p\n", i, &arr[i]); printf("p+%d = %p\n", i, p + i); } return 0; }

运行结果:
C|【C语言的灵魂】-指针(2)
文章图片

所以 p+i 其实就是在访问数组 arr 下标为i的地址,我们对它进行解引用就可以访问到数组的内容了.
那我们就可以直接通过指针来访问数组
int main() { int arr[] = { 0,1,2,3,4 }; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); int i = 0; for (i = 0; i < sz; i++) { printf("%d ", *(p + i)); } return 0; }

事实上,我们在对数组进行访问的时候arr[i],编译器会把它变成*(arr+i) ,所以,对指针的访问和对数组的访问是一样的,
二级指针
指针变量也是有它自己的地址,那我们可不可以再把指针的地址存起来?可以的.这就是二级指针.
如果你再把二级指针的地址存起来,那就变成了三级指针(及四级,五级....可以无限套娃)
C|【C语言的灵魂】-指针(2)
文章图片


a的地址存放在pa中,pa的地址存放在ppa中.
pa是一级指针,ppa是二级指针.
*ppa 通过对 ppa 中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .
对 pa 中的地址进行解引用,就找到的了 a ; 也可以**ppa .这样也能访问到 a .
指针数组
指针数组是一个存放指针变量的数组.
数组里面的元素可以是整型,浮点型,字符类型...指针也是一种类型,也可以在数组中存放,这就是指针类型的数组(简称为指针数组).
C|【C语言的灵魂】-指针(2)
文章图片

int main() { int a = 10; int b = 20; int c = 30; int d = 40; int e = 50; int* arr[5] = { &a,&b,&c,&d,&e }; //存放整型指针的数组 for (int i = 0; i < 5; i++) { printf("%d ", *(arr[i])); //依次对数组中的指针进行访问 } return 0; }

C|【C语言的灵魂】-指针(2)
文章图片


数组指针
数组指针就是一个存放整个数组地址的指针.
前面我们说过,不同类型的指针变量一次访问的内存大小是不一样的,我们有时候需要访问整个数组
就要用到数组指针.如果数组是存放整型的,那么数组指针的类型就是 int(*)[ ].

C|【C语言的灵魂】-指针(2)
文章图片


C|【C语言的灵魂】-指针(2)
文章图片

【C|【C语言的灵魂】-指针(2)】

    推荐阅读