初始指针
初始指针
what is 指针
- 指针描述了数据在内存中的位置
- 指针也就是内存地址
- 一个内存单元为一个字节
- 指针在32位平台是4个字节,在64位平台是8个字节
指针的意义
指针的类型决定了,指针解引用的权限有多大
1
2
3//例如
char*//可以指1个字节
int*//可以指4个字节
取地址运算
&:取地址后的,需要用%p输出,如果用%x(16进制),则会警告
只有明确的变量才能取他的地址
本地变量存放在堆栈的地方,内存地址由高到底
指针变量:用于记录地址的变量
int* p,q只将p设成指针,q只是普通变量
指针用于,函数的传址,当函数需要返回多个值时,需要用指针带回
指针与函数
传入函数的数组,函数接收到的是函数第一个数的地址,函数中设置接受的数组时,就是设置了指针
数组变量是特殊的指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17void minmax(int arr[])//这里
{
arr[0]=11;
}
//上面的函数还可以设置成
void minmax2(int* a)
{
a[0]=11;//与上面结果一致
}
int main()
{
int arr[]={};
minmax(arr);
printf("%d",arr[0])
return 0;
}
//结果是11,因为设置函数时,用了int arr实际上是设置了指针- 因此在使用数组作为函数变量时,有两种方法:
- int arr
- int* a
- arr的地址也就是arr[0]的地址
- 因此在使用数组作为函数变量时,有两种方法:
数组变量是
const
(限定的变量不允许被改变)的指针,所以不能被赋值,数组之间也不能互相赋值1
2
3
4
5
6
7
8//例子:
int main()
{
int a[]={1,2};
int b[]={};
a=b;//不能这样写
return 0;
}
指针与const
指针可以是
const
,修饰的值也可能是const
1
2
3
4int i=0;
const int *p=&i;
*p=25;//因为使用const修饰p所以不能再使用,*对i进行修改
//但是可以通过,直接对i进行修改判断被
const
的标志1
2
3const int* p1=&i;
int const *p2=&i;
//第一个和第二个是一样的,const在*的前面,表示所指的东西不能被修改,const在*的后面表示指针不能被修改const
修饰数组表示,数组里面的每一个元素都被const
指针的运算
- 指针+1,增加一个指针所指的类型,同理对n也有意义,对-也有意义,减出的结果是,差n个指针所指的类型(元素个数)
1 |
|
1 |
|
- 如果地址加1就没有实际意义
- 0地址, 是不能随便触碰的地址如果使用NULL效果和0地址一样,有些编译器,若果强制使用0地址,则可以用NULL
- 指针和指针相减的前提是两个指针指向同一个指针
- 指针加指针没有什么意义
指针的类型转换
- 强制类型转换,可以用于指针的赋值
指针的用处需要传入较大的数据用作参数
传入数组对数组操作
函数返回不止一个结果
用函数修改不止一个变量
动态申请内存
动态内存分布
malloc
:库函数为<stdlib.h>
向
malloc
申请的空间的大小是以字节为单位的,返回的结果是void*
,需要类型转换为自己需要的类型同时需要使用,
free()
将地址归还,括号里面填存储地址的变量,可以使用free(NULL)如果申请失败的话就会返回0或者NULL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include<stdio.h>
#include<stdlib.h>
int main()
{
int number;
int* a;
int i;
printf("输入空间大小");
scanf("%d",&number);
a=(int*)malloc(number*sizeof(int));
//第一个int*是将malloc返回值强制转换为int*,因为a是int*
//(number*sizeof(int)),*指的是乘法,number,是我们想要的大小,但是需要×相应的类型才能得到,
free(a);//使用malloc需要归还
}
使用
malloc
常见问题- 使用了
malloc
没有free - 错过了free的时机
free
再free
- 使用了
野指针
指针指向的位置是不可知的为野指针
造成原因
指针没有初始化
- 指针的初始化为NULL
1
2
3
4
5int *i;
*i=20;
//这里i 就是野指针
//因为i没有初始化,局部变量i默认为随机值,随机的位置来访问i,也就是非法访问指针越界也会造成野指针
1
2
3
4
5
6
7
8
9
10
11
12int main()
{
int arr[10]={0};
int* p =arr;
int i;
for(i=0;i<=10;i++)
{
*p=i;
p++;//这里需要循环10次,但是第10次的时候已经越界,这时候是野指针
}
return 0;
}指针指向的空间释放
如何有效规避野指针
- 指针初始化NULL
- 小心指针的越界
- 指针指向空间及时释放指针为NULL
- 检查指针的有效性
空指针没有权限使用
使用指针时,最好判断是否为NULL
1
2
3
4
5
6int *p=NULL;
if(p!=NULL)
{
*p=20;
}//最好判断一下,可以减少代码出错
指针的标准:
允许指向数组元素的指针指向数组后面一个地址,不允许指向前面一个地址
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include<stdio.h>
#define count 5
int main()
{
int arr[count]={0};
int *p=NULL;
int i=count;
for(p=&arr[count];p>&arr[0];)
{
--i;
*--p=i;
//先--,再解引用
printf("%d,%d\n",arr[i],*p);
}
return 0;
}
指针和数组
数组名:是数组首元素的地址
1
2
3
4int arr[10];
int *p=arr;
//*(p+2)<==>arr[3]<==>*(2+p)<==>*(2+arr)<==>*(arr+2)<==>2[arr]<==>p[2]
//因为编译器在编译的时候,将arr[2]-->*(arr+2),所以我们可以运用交换率,arr[2]=2[arr]
二级指针
指向指针的指针,被称作为二级指针
1
2
3
4
5
6
7
8int a=8;
//int为a的类型
int *pa=&a;
//*为指针变量,int 为a的类型
int* *ppa=&pa;//ppa是二级指针变量
//第二个*为指针变量,第一个int*为pa的类型
inte***pppa=&ppa;
//三级指针使用:
1
2
3*pa=a;
*ppa=pa;
**ppa=a;
指针数组
存放指针的数组
1
int* parr[10];//指针数组,cun'f
初始指针
https://tsy244.github.io/2023/04/20/C/初始指针/