目录
以后会经常发自己的学习历程,和学习心得,感兴趣的小伙伴可以点个关注支持一下!
一、何为指针?
指针,指针,而指针到底是什么?
其一:指针也可以理解为就是地址
其二:我们平常说的指针变量,就是用来存放内存地址的变量。
之前在scanf里面经常会忘记使用 & (取地址操作符),它取出的内存就是地址,而把地址放到一个变量中,这个变量便变成了指针变量。
include <stdio.h>
int main()
{
int a = 7;//在内存中的空间存放a
int *p = &a;//&a即使指针p指向a的地址
return 0;
}
注:指针是用来存放地址的。
在32位的平台中指针占4个字节,64位中占8个字节
二. 指针和指针类型
指针的类型跟变量的类型相仿,都有不同的类型。
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
NULL 指针是一个定义在标准库中的值为零的常量。
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
根据该代码我们可以看出,指针的类型为:" 类型 + * "
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。
其他类型也是同上
2.1指针的解引用
“解"就是把该地址对应的内容解开,解出来,那就是该变量的值了,所以称为"解引用”。
int a = 7;
int *p= &a; //定义一个整型指针p 并且p指向了a的地址 (&取地址)
*p=1; //解引用, 即 给a赋值10
注:指针解引用最多操作的字符由指针的类型决定。
eg:int* 的指针的解引用只能能访问四个字节。
3. 野指针
3.1.野指针出现原因
1.指针未初始化,指向不定
#include <stdio.h>
int main()
{
int *p;//指针未初始化,默认为随机值
*p = 7;
return 0;
}
2.指针越界访问
include <stdio.h>
int main()
{
int a[7] = {0};
int *p = a;
int i;
for(i=0; i<=8; i++)//i>7
{
//当指针指向的范围超出数组a的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
3.1.如何避免野指针
1. 定义指针时,对其初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5.使用指针之前,检查其是否有效
4.指针和数组
先看例子:
#include <stdio.h>
int main()
{
int a[]={1,2,3,4,5};
printf("a=%p\n",a);
printf("&a[0]=%p\n",&a[0]);
return 0;
}
可见数组名和数组首元素的地址是一样的
结论:数组名表示的是数组首元素的地址
那么我们可以了解到 p+i 其实就是计算数组a下标为i的地址。
那么我们就是直接通过指针来访问数组。
#include <stdio.h>
int main()
{
int a[]={1,2,3,4,5};
int i;
int * p=a;
for(i=0;i<5;i++)
{
printf("%d\n",a[i]);
*p++;//通过指针累加挨个输出数组中的元素
}
return 0;
}
5.二级指针
指针变量也是变量,是变量就在内存中占用一定的地址,那么指针变量的地址是什么呢?这就引入了一个新的概念:二级指针。
int a = 7;
int * p = &a;
int **ppa=&pa;
//a的地址存放在pa中,pa的地址存放在ppa中。
//pa是一级地址,而ppa是二级地址
对于二级指针的运算有:
*ppa通过对ppa中地址进行解引用,这样*ppa指向的就是pa。
int a = 7;
*ppa = &a;//等价于pa=&a
**pa先通过*ppa找到pa,然后找到*pa,*pa就等于a;
6.指针数组
指针数组其实是数组,不过指针数组里面存放的都是指针。
那指针数组是怎样的?
int* arr[3];//是什么?
//就是一个指针数组
arr是一个数组,有3个元素,每个元素是一个整形指针。只不过数组内的元素的类型都为int*。