嘉明的C学习之Day10-指针的传递与偏移

指针的传递与偏移

指针的传递

为了理解指针的传递,我们来看看下面这个程序

#include<stdio.h>
	void change(int j) {
		j = 5;//j是形参
	}
	int main() {
		int i = 123;
		printf("before:%d\n", i);
		change(i);//i是实参
		printf("after%d\n",i);
		return 0;
	}

注意:这里的i是主函数的局部变量。
change的目的就是改变实参的值。把i=123变成5,那上面这段程序可以实现吗?
在这里插入图片描述
从结果我们得知,change函数并没有实现它的功能。那为什么会这样呢?
有人就会问:“哎呀!你在上一篇文章中数组传递中也有过类似的操作,为什么数组就可以,上面程序这样就不行啊!?
别急,兄弟姐妹们听我细嗦
首先先来揭晓一下为什么会这样,其实函数是存在栈空间的。在我们主方法中定义了一个int i(局部变量),它就会生成一个四个字节大小的空间给i 同理,在change函数中也会生成一个四个字节大小的空间给j(局部变量)。这两个变量都有各自的地址,在主函数中的i只是传过去了值123,在change函数中执行j=5相当于给把j的值从123变成了5而已。
在这里插入图片描述

我们debug验证一下,可以看到传值过去的时候j的值就是123
在这里插入图片描述
点击下一步执行change(i),可以看到
0x0096FBFC 7b 00 00 00(i的地址与内存的值)
0x0096FB28 05 00 00 00(j的地址与内存的值)
只有j发生了改变i表示内心毫无波澜甚至有点想笑
在这里插入图片描述
所以输出的结果都是主函数中i原来的值是正确的。

那么解答第二个问题,我们上一篇文章中数组传递中也有过类似的操作,为什么数组就可以呢?
如果有认真阅读过文章的人肯定记得当时传参到方法中的数组我们sizeof运算符运算了一下大小是4个字节(因为定义的是int类型的数组),之后得出的结论就是传过了初始地址过去

那传地址这种事情不是只有指针才有的嘛,而且数组的变量本质就是指针变量啊。
欸!那如果我们这样试试会不会不一样
我们用&取i的地址,再用*取出地址所对应的值,再重新赋值。就好像这样

#include<stdio.h>
	void change(int *j) {
		*j = 5;//*j是形参
	}
	int main() {
		int i = 123;
		printf("before:%d\n", i);
		change(&i);//&i是实参
		printf("after%d\n",i);
		return 0;
	}

在这里插入图片描述
可以看到我们就这样成功了,因为我们从头到尾都是围绕i的地址和值在做事情。
这样的操作也叫做指针的传递。

指针的偏移

概念(复制粘贴的嘻嘻嘻嘻)
指针即地址,就像我们找到了一栋楼,这栋楼的楼号是B,那么往前就是A,往后就是C,所以应用指针的另一个场景就是对其进行加减,但对指针进行乘除是没有意义的,就像家庭地址乘以5没有意义那样。在工作中,我们把对指针的加减称为指针的偏移,加就是向后偏移,减就是向前偏移。

接下来我们用一个程序来理解指针偏移
比如有一个数组a,我们定义一个int指针变量p,通过指针偏移用p输出数组a各个元素的值
程序如下:

#include<stdio.h>
#define N 5
int main() {
	int a[N] = { 1,2,3,4,5 };
	int* p = a;//对一个指针进行取值,得到的类型是其基类型(比如这里取值就得到是int类型)
	//上面的语句等价于
	// int *p;
	//p=a;
	for (int i = 0; i < N; i++) {
		printf("%d\n", *(p + i));
	}
	return 0;
}

在这里插入图片描述
讲解:
我们用定义指针变量后用 p=a,使数组a的初始地址赋给p,然后用指针偏移循环输出数组a的元素,*p+0等于a[0] (因为初始地址本来就是a[0]的值,所以p+0就算a[0]的地址),*p+1等于a[1](向下偏移一个单位),这样依次输出全部元素。
从监视我们可以看到p的值就是a的地址,✳p+0就是1
在这里插入图片描述

注意:指针加减叫做偏移,是和我们平时的运算不太一样的。上面的p+i是指针偏移,不是我们所理解简单的加减法。
比如i=1时,p+1不是地址向下移动一个字节,而是移动(p+(1*p的基类所占字节大小)
因为我们定义的是int ✳p;int类型是4个字节。即取p地址的向下4个字节的值
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值