注:按照鹏哥c语言的课记得笔记
指针定义
通过存储在内存中的一个地址(一个编号)来找到存储在另一个内存中的数据(精准定位),指针就是变量,用于存放内存地址的变量
//举例
int a = 10; //占4个字节
int* pa = &a; //拿到的是a的4个字节中第一个字节的地址
//pa为一个指针变量;*pa 通过访问a的地址找到a,进而修改a的值,称为解引用
指针和指针类型
类型: int* , float* ……
指针类型的意义: 为什么指针大小都一样,却要定义多个类型的指针呢,为什么不定义一个通用的?(32位系统举例)
指针的解引用: 指针决定了指针解引用的权限(访问权限)有多大,不同的指针类型是有区别的
int* 4 bytes
char* 1 bytes
......
例子
int a = 0x11223344;
int * pa = &a;
*pa = 0;
/*
a的值的变化:
11 22 33 44
-->
00 00 00 00
*/
int a0x11223344;
char * pa = &a;
*pa = 0;
/*a的值的变化:
11 22 33 44
-->
00 22 33 44
步长
指针类型决定了,指针走一步,能走多远(步长)
int* 4 bytes
char* 1 bytes
......
例子1:
int main(){
int arr[io] ={0};
int *p = arr;
char *pc = arr;
printf("%p\n",p);//004FFC40
printf("%p\n",p+1);//004FFC44
//或者
printf("%p\n",pc);//004FFC40
printf("%p\n",pc+1);//004FFC41
return 0;
}
例子2:
int main()
int arr[l0] = { 0 };
int *p = arr;
int i = ;
for(i =0; i<10;i++){
*(p + i) = 1;
}
return O;
}
//p+i表示下标为i的地址,这里把数组的数据全改为1
野指针
概念:指针指向的位置不可知
成因:
指针未初始化
int main(){
//这里的P就是一个野指针
int* p://p是一个局部的指针变量,局部变量不初始化的话,默认是随机值
*p = 20://非法访问内存了
return 0;
}
指针越界
int mainO
int arr[10]={0};
int *p = arr;
inti=o;
for(i=0; i<=10: i++) {
//当指针指向的范围超出数组arr的范围时,p就是野指针
*p = i;
p++;
}
return O;
}
指针指向的空间释放
int* test() {
int a = 10;
return &a;
}
int main() {
int*p = test();
*p = 20;
return O;
}
如何规避
指针初始化
小心指针越界
指针指向空间释放即使置NULL
指针使用之前检查有效性
指针运算
指针加减整数
#define N_VALUES5
float values[N_VALUEs];
float *vp;
//指针+一整数:指针的关系运算
for (vp = &values[O]; vp < &values[N_VALUEs];) { //vp < &values[N_VALUEs]指针关系运算
*vp++ = 0://这里等价于*vp = 0; vp++;
}
//首先注意: a++与++a的区别,虽然++a和a++等价的结果一样,但是运算过程不同,a++ 是先使用a的值,然后再对a做加1处理,++a是先对a作加1处理,然后再使用a的值。
指针减指针
指针 - 指针的前提: 两个指针指向同一个空间
int main(){
//首元素 - 尾元素地址 = 元素个数
int arr[10] = { 0 };
printf("%d\n",&arr[0]);
printf("%d\n",&arr[9]);
printf("%d\n",&arr[9] - &arr[0]);//这里输出的是9,而不是36,这就是指针 - 指针的关系,按照数字减去数字的逻辑,是36,但这是指针减指针的逻辑
char c[5] = {0}
printf("%d\n",&arr[9] - &c[0]);//err
return 0;
}
指针关系运算
int main() {
int arr[10] = ( 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
int* pend = arr + 9;
while(p==pend) {
printf("%d\n",*p);
p++;
}
return 0;
}