实参形参与指针2——函数值传递与地址传递

前言

在复习和实现完顺序表的定义及基本操作之后,我准备去复习单链表的基本概念,不过还是不出以外的遇到了一些基础性的问题,于是便有了这篇记录性的文章

C函数的值传递与地址传递

正如昨天的记录中提到的,在定义某个函数的时候,你需要告诉这个函数传入的变量是否需要修改,不需要修改就传形参,需要修改就传入实参。

typedef struct{
	int data[9];
	int dataLength;
}SList;

void printAllElem(SList list){
	int i = 0;
	for(i=0;i<list.dataLength;i++){
		printf_s("%d\n",list.data[i]);
	}
}//打印所有元素,不需要修改

bool deleteHeadElem(SList &list){
	int i = 0;
	for(i=1;i<list.dataLength;i++){
		list.data[i-1] = list.data[i];
	}
	list.dataLength--;
}//删除第一个元素,需要修改

int main(){
	SList list;
	initList(list);
	printAllElem(list);
	deleteHeadElem(list);
}

可以看到上面代码中,定义了一个顺序表结构体SList和两个功能函数。其中printAllElem函数不需要对顺序表进行修改,于是传入了结构体(数值变量)本体;而deleteHeadElem函数需要对顺序表进行修改,于是传入了结构体变量的地址。
从这里就可以初见端倪,在定义函数时,直接进行值传递就是在传递形参,而传递地址就是传递实参。
而在引用的时候,不难发现两个函数传入的参数长相是一样的,尤其是printAllElem函数在引用时竟然丢了取地址符号!这是因为取地址是一种对数值的操作方式,而SList list本身不是地址值,所以要在声明时把这个list告诉函数之外,还要告诉函数别忘了取出它的地址才行。也正因为如此,main中调用printAllElem函数的时候只需要传入list就行了,就不再需要告诉函数怎么操作才能取地址了。
那么如果是对结构体指针进行操作呢?有了上面的理解很快就能改出下面的代码了。

typedef struct{
	int data[9];
	int dataLength;
}SList;

void printAllElem(SList list){
	int i = 0;
	for(i=0;i<list->dataLength;i++){
		printf_s("%d\n",list->data[i]);
	}
}//打印所有元素,不需要修改

bool deleteHeadElem(SList* list){
	int i = 0;
	for(i=1;i<list->dataLength;i++){
		list->data[i-1] = list->data[i];
	}
	list->dataLength--;
}//删除第一个元素,需要修改

int main(){
	SList list;
	SList* Plist = &list;//Plist本身存的就是地址
	initList(Plist);//直接传入Plist就相当于地址传递
	printAllElem(*Plist);//不修改顺序表,所以要传递数值,要把Plist存的地址值里对应的数据找出来,所以传入的是*Plist
	deleteHeadElem(Plist);
}

抛砖引玉

  • 在顺序表中,指针是为了方便修改顺序表元素而服务的,属于额外选项。
  • 在单链表中,由于单链表在内存的物理结构中是离散的,所以天生必须要依靠指针去完成基本操作。
  • 在单链表中,指针除了服务与“数值”,指针本身也要被修改,这也是链表逻辑理解和实现上的难点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值