C语言指针感悟

        重温C语言的指针,有了一些不同的感悟,记录一下的同时也分享一下,欢迎指出错误。

       首先,要学习一些前提知识,程序中的变量是通过地址来存储和调用的,存储单元的内容和地址是不同的内容,就相比房间的编号和房间里住的人是不同的,而且啊,住这个酒店的人都比较豪,有一个人就包下了从房间编号2000到2003这4(一个长度为4 的整形变量)个房间。当你要找一个人(变量)时,你去问前台工作人员,前台工作人员告诉你要找的人在2000号房间,本来你毫无方向,但这个2000就给了你明确的指向,所以这个房间编号2000(地址)就称为指针,这个前台工作人员存有2000,就称为指针变量,这也就是指针和指针变量定义的区别。

      住这个酒店的客人是分群体的,有一些一次包4个房间,有一些一次包1个,而且他们也会找他们指定的工作人员来进行登记入住,因为只有指定的工作人员知道他们一次会包多少,有钱人懒得每次解释,还不如就找熟人,这也就是指针的基类型。假设有一个整形指针 int *p;*表示“指向”,p存储的是房间编号(地址),*p就是指向房间编号2000的客人(地址存放的内容)。

      在进行指针变量的初始化时需要注意以下几点:
 

//这么初始化时是正确的
int *p=&a;
//p表示的是地址,*p表示的是地址内存放的值
int *p;
*p=100;    //这么初始化是错误的,但如果p已经有了明确的指向就可以这么赋值

p=&a;
*p=100;    //这种操作才是Good

           一个简单的判断两个数最大的值的程序,体验一下指针的使用

#include<stdio.h>

int main(){
	int *p1,*p2,*p,a,b;
	scanf("%d%d",&a,&b);
	//将p1指向变量a
	p1=&a;
	//将p2指向变量b
	p2=&b;
	//输出p1和p2指向的地址
	printf("p1=%d\tp2=%d\n",p1,p2);
	if(a<b){
		//如果b是较大值,则利用中转指针p将p2中存储的b变量的地址和p1中存放的a变量的地址进行交换,使得p1指向b,p2指向a
		p=p1,p1=p2,p2=p;
	}
	printf("a=%d\tb=%d\n",a,b);
	printf("p1=%d\tp2=%d\n",p1,p2);
	printf("max=%d\tmin=%d\n",*p1,*p2);
	return 0;
}

       从输出也可以看出,在a<b时,a、b变量的值并没有变量而是p1和p2指向的地址发生了交换,当然,也可以不使用中转指针,可以直接p1=&b,p2=&a。

      将上面的程序稍微变形

#include<stdio.h>

void swap(int *p1,int *p2){
	//利用中转变量,直接交换p1和p2指向地址的内容
	int temp;
	temp=*p1;
	*p1=*p2;
	*p2=temp;
}


int main(){
	int *p1,*p2,a,b;
	scanf("%d%d",&a,&b);
	//将p1指向变量a
	p1=&a;
	//将p2指向变量b
	p2=&b;
	//输出p1和p2指向的地址
	printf("p1=%d\tp2=%d\n",p1,p2);
	if(a<b){
		swap(p1,p2);
	}
	printf("a=%d\tb=%d\n",a,b);
	printf("p1=%d\tp2=%d\n",p1,p2);
	printf("max=%d\tmin=%d\n",*p1,*p2);
	return 0;
}

      

       很明显,p1还是指向a,有一些人可能会有疑问,上面是交换指向地址,写成函数为什么就变成交换指向地址里的内容了,那我在函数里面交换指向地址呢,我将swap函数替换成下面的代码

void swap(int *p1,int *p2){
	int *temp;
	temp=p1;
	p1=p2;
	p2=temp;
}

       可以看出输出不符合我们的意愿,为啥呢,这是因为实参p1向函数的形参p1传递是单向的,如果我直接改变传过来的地址里面的值,那就不需要传回值,但如果我改变是指向的地址,需要传回,但传不回去,所以,就尴尬了。

       接下来看看通过指针引用数组,这对于初次接触数组的可能有些难度,先介绍一下数组的基础知识,数组嘛,顾名思义就是数据的组队,都要组队了,肯定要一类的才能组队,都组队了,那肯定住在一堆,才显得关系特殊嘛,这也就是数组的定义:相同的数据类型占用连续的存储空间,这个组取了个名字,通过这个名字就可以找到组内的第一个房间,所以数组名不代表整个数组,只代表数组首元素的地址,所以在指针指向时,就可以这样p=&a[0];还可以这样p=a;知道了第一个房间,那怎么找到后面的房间呢,前面说过工作人员知道这群人的习惯,知道一次会包几间房,所以,加1就是下一个客人的房间,减1就是上一个客人的房间。

     下面就来看一个通过数组和指针来求1+2+...+10的值的程序:

#include<stdio.h>

int main(){
	int a[10],*p,i,s=0;
	for(i=0;i<10;i++){
		a[i]=i+1;
	}
	for(i=0;i<10;i++){
		printf("%d\t",a[i]);
	}
	printf("\n");
	p=a;
	for(i=0;i<10;i++){
		//用p+1来指向下一个数组元素
		s+=*(p+i);
	}
	printf("sum=%d\n",s);
	return 0;
}

        反正每次加1,能不能用p++呢,使用是没问题的,但使用情况有点混乱,需要比较一下

p++;*p    p++先将p指向下一个数组元素,然后在取值

*p++       由于++和*同级,结合方向为从右到左,等价于*(p++),先引用p的值,调用*p,在p++,指向下一个数组元素

*(p++)*(++p)  懂i++和++i的应该知道,前者就是上面的用法,后者先将p指向下一个数组元素,在取出来

++(*p)      将*p的值取出来,假设就是i吧,++i,所以就是使p所指向的数组元素加1

其他组合一样的分析方法,就不列举了。

        我们试着将上面的程序,改写一下并用函数实现求和

       可以看出结果是一样的,可能聪明的你已近发现了实参数组在向形参数组传值的时,传的时数组名,也就是首元素的地址,所以形参也可以看成一个指针变量,实际上,C编译都是将形参数组名作为指针变量来处理的,所以,函数也可以写成

void fun(int *t,int n),有兴趣的可以尝试一下,用指针指向一维数组是很简单的,但现实中用的还是二维数组,也就是矩阵,只多了一维,但用指针指向时却比指向一维数组复杂多了,先来简单介绍一下二维数组。

      a[4][4],可以理解为就是一个4*4的矩阵,包括4行,a[0],a[1],a[2],a[3],a[0]又包括a[0][0],a[0][1],a[0][2],,a[0][3],同理a[1]包括a[1][0],a[1][1],a[1][2],,a[1][3],剩下的就一样了,数组名a还是代表首元素的地址,但a+1不是代表a[0][0]地址,而是代表a[1][0]的地址,因为二维数组可以理解为多个一维数组嘛,所以a[0][1],a[0][2]这些都是跟着a[0][0]的,那么问题来了,怎么指向后面的元素地址呢,*(a+1)+2,也就是代表了&a[1][2]的地址,使用方法就和普通的指针是一样了,这里不加以赘述了。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值