C语言之指针的本质及指针的传递

一、指针

1.1 指针的本质

1.1.1 指针的定义

​ 内存区域中的每字节对应一个编号,这个编号就是“地址”。如果在程序中定义了一个变量,那么在对程序进行编译时,系统就会给这个变量分配内存单元。按变量地址存取变量值的方式称为“直接访问”;另一种存取变量值的方式成为“间接访问”,即将变量i的地址存放到另一个变量中。C语言中,指针变量是一种特殊的变量,它用来存放变量地址。

指针变量的定义格式:

基类型 *指针变量名;

​ 指针与指针变量是两个概念,一个变量的地址称为该变量的“指针”。如下图,地址2000是变量i的指针。如果有一个变量专门用来存放另一变量的地址(即指针),那么称它为“指针变量”。例如下图中的i_pointer就是一个指针变量。

1.1.2 取地址操作符与取值操作符

​ 取地址操作符为&,也称引用,通过该操作符我们可以获取一个变量的地址值;取值操作符为*,也称解引用,通过该操作符我们可以得到一个地址对应的数据,如下图所示。

在这里插入图片描述

注意以下3点:

  1. 指针变量前面的“*”表示该变量为指针型变量。如下:

float *pointer_1;

​ 注意:指针变量名是pointer_1,而不是*pointer_1。

  1. 在定义指针变量时,必须指定其类型。需要注意的是,只有整型变量的地址才能放到指向整型变量的指针变量中。例如以下的赋值就是错误的。

float a;

int *pointer_1;

pointer_1 = &a; //毫无意义而且会出现错误

  1. 如果已执行了语句

pointer_1 = &a;

​ 那么&* pointer_1的含义是什么呢?

​ “&”和“*”两个运算符的优先级相同,但是要自右向左的方向结合。因此&*pointer_1与&a相同,都表示变量a的地址,也就是pointer_1。

​ *&a的含义是什么呢?

​ 首先进行&a运算,得到a的地址,在进行*运算。*&a和*pointer_1的作用一样的,他们都等价于变量a,即*&a与a等价。

1.2 指针的使用场景

​ 指针的使用场景只有两个:即传递和偏移。

1.2.1 指针的传递

在这里插入图片描述

​ 原理图如下图所示。程序的执行过程,我们需要关注的是栈空间的变化。当main函数开始执行时,系统会为main函数开辟函数空间,当程序走到int i时,main函数的栈空间就会为变量i分配4字节大小的空间。调用change函数时,系统会为change函数重新分配新的函数栈空间,并为形参变量j分配4字节大小的空间。在嗲用change(i)时,实际上是将i的值赋值给j,我们把这种效果成为值传递(C语言的函数调用均为值传递)。因此,当我们在change函数的函数栈空间内修改变量j的值后,change函数执行结束,其栈空间就会释放,j就不再存在,i的值不会改变。

问题:难道就不能在子函数中修改main函数内的某个变量的值?答案是可以的,修改程序如下:

#include<stdio.h>
//C语言形参的位置不能出现&,因为C语言不支持引用
void change(int *j)	//j叫形参
{
	*j = 5;	//间接访问
}

//指针的传递使用场景
int main()
{
	int i = 10;
	printf("before change i=%d\n", i);
	change(&i);//i叫实参,实参赋值给形参的过程,实参可以是变量,可以是表达式 
	printf("after change i=%d\n", i);
	return 0;
}

在程序执行后,打印的i的值为5,难道C语言函数调用值传递的原理变了?并非如此,我们将变量i的地址0x0099FC38传递给change函数时,实际效果是j=&i,依然是值传递,只是这时我们的j是一个指针变量,内部存储的是变量i的地址,所以通过*j就间接访问到了与变量i相同的区域,通过*j=5就实现了对变量i的值的改变。如下图所示,我们依然可以看到变量j自身的地址是0x0099FB64,它与变量i的地址不相等。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值