【C语言】函数参数试探:传指针与传引用——以队列为例

首先,实现一个简单的队列:

#define	Maxsize 100
#define ElemType int

//队列
typedef struct Queue{
	ElemType data[Maxsize];
	int head,rear;
}Queue;

void InitiateQueue(Queue &s) {
	s.head = s.rear = -1;
}

01 用指针写队列的pop和push函数:

void pushQ(Queue *s,int x) {
	s->data[++s->rear] = x;
}

void popQ(Queue *s, int& x) {
	x = s->data[++s->head] ;
}

对应的调用方法是:

int main() {
	Queue qa, * s;
	InitiateQueue(qa);
	s = &qa;  //"&"在这里起到了取地址的作用

	int x,y;
	for (int i = 0; i < 5; i++) {
		scanf_s("%d", &x);
		printf("接收到输入x=%d \n",x);
		pushQ(s,x); //s是指向[Queue]这个数据结构的指针
	}

	for (int i = 0; i < 5; i++) {
		popQ(s,y);  //s是指向[Queue]这个数据结构的指针
		printf("现在出队的是:%d", y);
	}
}

02 用引用写队列的pop和push函数:

void pushQ(Queue &s,int x) {
	s.data[++s.rear] = x;
}

void popQ(Queue &s, int& x) {
	x = s.data[++s.head] ;
}

对应的调用方法是:

int main() {
	Queue qa, * s;
	InitiateQueue(qa);
	s = &qa;

	int x,y;
	for (int i = 0; i < 5; i++) {
		scanf_s("%d", &x);
		printf("接收到输入x=%d \n",x);
		pushQ(qa,x); //qa在这里是一个[Queue]类型的数据
	}

	for (int i = 0; i < 5; i++) {
		popQ(qa,y);  //qa在这里是一个[Queue]类型的数据
		printf("现在出队的是:%d", y);
	}

}

我们来选几句比较一下:

传指针void pushQ(Queue *s,int x)pushQ(s,x);
传引用void pushQ(Queue &s,int x) {pushQ(qa,x); 

对于pushQ函数,我们希望传进去的队列可以得到修改,并在接下来的程序中使用。所以不能直接传Queue类型变量,因为按相关规定(实际参数与形式参数的关系),这相当于在函数中又创建了一个Queue类型的变量,把我们传进去的Queue类型变量的值赋给了它,修改了这个在只在函数中存在的变量,我们原来的值并没有被改变;

而上述两种方法都可以实现在我们传进去的内容上修改。

第一种,我们给的实际参数是s,一个[Queue]类型的指针;函数中的形式参数也是一个[Queue]类型的指针(为了方便我也起名为s了,姑且在这里叫它s2)。执行函数时,s的值————即我们的[Queue]类型数据qa的地址被从一个指针赋给另一个指针,对队列的所有的操作都是对这个地址完成的。所以即使函数结束,形式参数s2完成使命消逝了,对队列的改变也依然有效。

第二种,我们给的实际参数是qa,一个[Queue]类型的数据(变量),也是我们要修改的内容;函数中的形式参数是一个[Queue]类型的引用&s。参考其他教程知道,引用相当于另起一个名字。执行此函数时,相当于进行了Queue &s=qa;

那这个"&"出现在赋值号左边好像就不是取地址的意思,而是做引用(为什么说好像,因为我也不是很确定...)所以与Queue s = qa本质的区别是,前者的s是qa的别名,对s的任何操作,对qa也同样生效,而后者是把qa的值给赋给s,对s的操作和qa无关。如此,我们需要用前一种来实现对传进去的参数本身的改变。

———————————————————————————————————————————

写这篇文的原因是我老是分不清在函数的定义中为形式参数加*和&,与在调用函数时为实际参数加*和&的区别...经过多番查阅和几轮踩BUG尝试,有了以上体会。作为一名可爱的小白,有理解有误之处,欢迎大家指正。我也会继续学习,有新的认识再回来补充。

(小结:声明变量时用的*表示声明了一个指向对应类型的指针,但如果跟在一个实际存在的变量前面,则表示取这个地址上对应的内容——所以这个变量也必须是指针变量;&用在赋值语句的右边一般表示取地址,取这个变量的地址,而声明变量时在赋值号左边用则表示引用,给这个变量起一个别名。以一个简单的小尝试结束本文:)

int main() {
	int a=10;
	int* p1; //声明int型指针
	p1 = &a; //取int型变量a的地址赋给指针p1
	int& b = a;  //为a创建了一个别名b

	printf("开始时的a:  %d\n", a);
	*p1 = 20;     //将p1所指向处,即a的内容修改为20
	printf("*p1 = 20;后的a:  %d\n", a);
	b = 30;       //将别名b的内容修改为30
	printf("b = 30;后的a:  %d\n", a);
}

/*输出如下:

开始时的a:  10
*p1 = 20;后的a:  20
b = 30;后的a:  30

*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值