v72.指针补充

1.指针作为函数参数

调用函数时,传递参数的形式决定了是否可以修改这些参数。

  • 传值方式:传递了参数给函数,并且这个参数是基本数据类型,如(int,float),那么函数内对参数的任何操作都不会改变这个原始变量的值。因为实际上传入函数的参数是一份copy,在函数内的操作只会影响到copy。
#include <stdio.h>
void increase(int a)
{
	a++;
}
int main()
{
	int num = 9;
	increase(num);
	printf("%d", num);
	return 0;
}
打印的结果还是9,并未改变原始参数num的值
  • 传址方式:可以做到在函数内真正修改参数的值,需要通过传递指向参数的指针,函数可以直接访问参数所处的内存地址,并修改其内容。
#include <stdio.h>
void increase(int *a)
{
	(*a)++;
}
int main()
{
	int num = 9;
	int *p = &num;
	increase(p);//传的是num的地址
	printf("%d", num);
	return 0;
}

2.指针的使用

  • 应用场景一:交换两个变量的值
    在这里插入图片描述
    函数内部的参数为 指针 的时候,调用函数的时候要传入 变量的地址

函数要返回多个值,那某些值就只能通过指针返回。既要返回a,又要返回b。传入的参数实际上是需要保存带回的结果的变量

  • 应用场景二:函数的返回结果有多个(需要保存改变值后的多个变量)
    在这里插入图片描述
    可以看到这种指针操作其实都是没有return值的,因为函数的返回值只能有一个!所以直接通过指针访问变量,对多个变量的值进行更改。
    之前讲过,如果不用指针的话,在一个函数内部是不能改变外部变量的值的:如果函数内没有返回值并且给到变量进行接收,而是单纯地传入一个变量的值(例如只是单纯执行操作increase(a);)那么传入函数的变量的值不变。但是如果使用指针,并且传入变量的地址,那么即使函数没有返回值,在函数内部仍然可以做到对变量值的修改。
  • 应用场景三:函数返回运算的状态,结果通过指针返回
    在这里插入图片描述这种情况,程序可能会出错,那么我将会使用return返回函数执行的状态,用指针改变变量的值
    在这里插入图片描述
  • 常见错误
    定义了指针变量,但是没有让他指向任何变量就开始使用指针(未初始化指针)
    在这里插入图片描述

3.指针和数组

将数组作为函数参数传入,数组此时实际上是指针
(以前文章有整理)

4.指针和const

在这里插入图片描述

int const *p = &i;

不能变的是 指向的变量
q是const指针,指向了变量i。那么q只能指向i而不能指向其他变量了。对*q进行赋值是可以的,因为i不是const变量。

在这里插入图片描述不能变的是不能通过p去做修改*p = 10;
这时可以让p指向别的变量,也可以修改 i 的值:*p = &j; i = 10;

  • 要么指针指向不可修改,要么不可通过指针修改
    在这里插入图片描述
    const在星号前面,不可通过指针修改;
    const在星号后面,指针指向不可修改。

在这里插入图片描述能用比较小的字节数传递值给参数:例如,一个超级大的数组,但是他传入函数的时候其实是一个指针的大小。

在这里插入图片描述这表明a[0],a[1]…a[5]全部都是const类型,不可改变。
在这里插入图片描述那么这种操作可以保证传入函数的数组不会被修改

5.指针运算

  • 指针加法运算
    在这里插入图片描述可以看到,对指针的值+1,不是在地址值上 +1,而是在地址值上 +sizeof(类型)
    在这里插入图片描述对指针 +1,是让指针指向下一个单元,根据具体的数据类型进行地址值的改变。
    关于指向下一个单元的操作:
    在这里插入图片描述

在这里,*(p+n) 和 a[n] 以及 p[n] 是等价的

在这里插入图片描述

  • 指针的值之间相减
    在这里插入图片描述得到的结果是 地址相减/sizeof(类型)
  • 关于*p++
    在这里插入图片描述*p++ 表示先取当前指针指向的值(*p),顺便对指针进行递增(p++)。通常用于对数组的一些操作,例如遍历数组:
    在这里插入图片描述
  • 指针的比较

在这里插入图片描述eg, a[0] < a[5]

  • 零地址
    在这里插入图片描述

如果int *p = 0;或者写成int *p = NULL;那么这表示指针p的初始化是0地址,如果再进行p = malloc(1);这种操作是不被允许的,因为程序会因为向0地址写入而退出

  • 指向不同类型的指针不可以相互赋值
    比如int *p = a[0];char *q = b[1];p = q;不可以执行。
  • 指针的类型转换
    在这里插入图片描述
int i = 9;
int *p = &i;
(void*)q = (void*)p;

在这里把int类型的p强制转换成void类型,交给void*q。但是并没有改变i的类型,i还是int型,只不过q也指向了i,通过q去看i当做void。

6.动态内存分配

  • 当不确定数组的大小的时候(或者说只有于运行的时候数组的大小才确定),C99通常可以使用可变数组:
int N;
printf("请输入你所需要的数组的大小");
scanf("%d",&N);
int a[N];
//在这里N是一个变量,它的值在定义数组a之前被确定
  • 但是C99之前就得使用动态内存分配:
    使用malloc函数 :
int N;
printf("请输入你所需要的数组的大小");
scanf("%d",&N);
int *a;
a = (int*)malloc(N*sizeeof(int));
...
free(a);

注意malloc函数的使用得引用头文件 #include <stdlib.h>。malloc函数要的不是数组要占据多少个单元,而是要知道占用多少个空间,单位是字节它返回的结果是 void*,但是数组a的类型是 int*,那么就得进行强制转换在这里我们需要的类型int *。OK操作完成,因为数组和指针是近似的,之后所有的事情就拿a当做数组来用。malloc函数为a借来了一块空间,之后要在程序的结尾将内存释放free(a);
在这里插入图片描述
但是空间申请失败了,就会返回0或者叫做NULL。
最好的习惯是,每当使用malloc函数就用free那个变量。

7.总结

在这里插入图片描述//第一周的指针操作,后两节的字符串和字符串操作没学。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值