11-C语言学习-指针
指针
功能
程序更加简洁高效
指针可以直接访问内容空间
概念
地址:
为了区分内存中的不同空间,编号称为该空间的地址,按照字节进行编址,16进制。
编址的范围,取决于计算机的位数(总线)64位-地址总线64位(64对01)-8字节
可以被寻址的范围 0x0000000000000000 - 0xFFFFFFFFFFFFFFFF(16)
1 个十六进制数字:0~F 等价 0000 ~ 1111(4bit)
指针:
简单理解为地址,指向某空间地址的指针
指针有类型,且有指向空间大小的含义
指针变量: 数据类型 *变量名 int *p; int *p, *q; 不要连续定义多个指针变量,最好一个一个定义 ,不指定存储类型默认为auto,不初始化为随机值(野指针)
野指针:
未经初始化的指针,或指向已经被释放空间的指针
不要使用未经初始化的指针
空指针:
NULL
int *p = NULL;(指针清零,空,指向内存地址为0x0的空间
0x0地址空间只读的(不能写),所以对空指针取*,会程序崩溃
指针类型:
int *p(4字节); char *p(4字节); float *p(1字节); double *p(8字节);
不同类型的指针,占用空间一样8字节,不同类型的指针,指向的空间大小不同
指针定义:
指针变量本身
p:操作指针变量本身
指针指向的空间
*p:操作指针变量指向的空间
将指针存放到一个变量中
用来存放指针的变量称为指针变量
8个字节,(64位计算机-8字节)所有类型指针变量都是8个字节,64位计算机
使用指针变量的值等价与使用某个指针,所以也会将某个变量简称为指针
指针相关的运算符
1.&取地址运算符
获得变量在内存空间中的地址,(首地址)(不能是常量-编译为指令在CPU中) int num = 100; &num
1.只有左值能完成取地址操作,常量和表达式不能
如int 4个字节,取的是第一个字节的地址
2.&连接的表达式一定有值,值为该变量在内存中存放的首地址
3.&连接的表达式一定有类型,类型具有升级的效果 int - int*
每次执行程序会重新分配空间,每次取地址不一样
printf("%p\n", &num); // ✅标准打印地址写法
2.取*值运算符
只有指针类型能够*操作,普通变量不行
*连接的表达式一定有值,值为指针指向的空间,以首地址开始,指向数据类型大小的数据的值 printf("%d\n", *&num);
*连接的表达式类型,类型具有降级的效果 int* -> int
*连接的表达式作为左值,就是将右边的值放入指向的空间。 *&num = 200;
3.指针的算数运算
+ - * / %
一般为加,减,加加,减减
int *p = NULL; p = p + 1; 0x0 -> 0x4
++;向内存高地址偏移指向数据类型大小个字节空间
--;向内存低地址偏移指向数据类型大小个字节空间
两个指针相减,两个地址之前差了多少个数据类型的元素
*p++,*与++同为单目同级别,自右到左,
4.指针的操作
对指针变量本身的p本身赋值,可以修改指针的指向
对指针变量p取*赋值,不修改指针的指向,而是利用指针修改空间的数据
5.指针作为函数参数的作用
1.值传递
实参将值传递给形参,形参改变不会影响实参
函数体内想使用外部变量值的时候使用值传递
使用指针可以跳出局部变量的作用域
2.地址传递
实参地址传递给形参,形参是实参的指针,可以利用形参修改实参的值
函数体内想修改函数体外部变量的值,使用地址传递
利用地址传递可以实现函数返回多个值
函数类型 fun(int *pnum1, int *pnum2)
{
tmp = *pnum1;
*pnum1 = *pnum2;
*pnum2 = tmp;
}
int a = 100;
int b = 200;
fun(&a, &b);
6.指针与数组 (数组用来储存,指针用来操作)
数组与指针的关系
数组的数组名是指向数组第一个元素的指针常量,常量无法被赋值(a++, a--, a += 1这些属于赋值)或改变(改变a)
可以将数组名a理解为int *型,有两种情况不能理解为int *型
1.sizeof运算时,数组名不能理解为int *型,此时为数组所占空间大小,不一定是8位
2.&运算时数组名不能理解为int *型
对数组名a进行取*降级为int型,取得就是数组一个元素的值,*(a + 1)取的是数组第二个元素的值
p = a;
p = &a[0];
所以,a[n] == *(a + n) == *(p + n) == p[n]
C语言中[]可以搭配指针使用,p[n]等价于指针+n再取*
C语言中,1.跨作用域使用指针,2.提供了一种间接访问变量的方式,特别是一些没有名字的空间,如数组
7.一维整形数组的传参
int a[5];
int fun(int array[], int len); //传的也是指针
int fun(int array[5]); //传进来其实是个指针,不是数组
int fun(int *parray, int len); //直接传入指针
