目录
指针的运算
指针+-整数
指针+-整数 就是对内存访问的时候应该跳过多少个字节,在之前已经介绍过来,这里就不说了
指针-指针
这个东西在数组中是很常见的,指针-指针 表示的是两个指针之间元素的个数
就像这样,低地址- 高地址,就会变成负的.
用指针-指针的方法实现strlen函数
#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
assert(str);//判断指针是否错误
char* tmp = str;
while (*++tmp)
{
;
}
return tmp - str;
}
我还写了很多库函数的实现,大家有时间可以看看: 各种库函数的实现
指针和数组
从调试中可以看出: 数组名和数组首元素的地址是一样的
所以: 数组名表示的是数组首元素的地址。
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;
}
运行结果:
所以 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) ,所以,对指针的访问和对数组的访问是一样的,
二级指针
指针变量也是有它自己的地址,那我们可不可以再把指针的地址存起来?可以的.这就是二级指针.
如果你再把二级指针的地址存起来,那就变成了三级指针(及四级,五级....可以无限套娃)
a的地址存放在pa中,pa的地址存放在ppa中.
pa是一级指针,ppa是二级指针.
*ppa 通过对 ppa 中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .
对 pa 中的地址进行解引用,就找到的了 a ;也可以 **ppa .这样也能访问到 a .
指针数组
指针数组是一个存放指针变量的数组.
数组里面的元素可以是整型,浮点型,字符类型...指针也是一种类型,也可以在数组中存放,这就是指针类型的数组(简称为指针数组).
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;
}
数组指针
数组指针就是一个存放整个数组地址的指针.
前面我们说过,不同类型的指针变量一次访问的内存大小是不一样的,我们有时候需要访问整个数组
就要用到数组指针.如果数组是存放整型的,那么数组指针的类型就是 int(*)[ ].