论函数形参与实参的常见错误篇

1、形参与实参的类型不一致引发的错误,
例子1如下

#include<stdio.h>
#include <sys/select.h>

int add(int *pdate)
{
	pdate[0] = 2;
	pdate[1] = 5;
}

int main()
{
	short int  buf[2] = {0};
	add(buf);
	printf("buf[0] = %d\n",buf[0]);
	printf("buf[1] = %d\n",buf[1]);
	return 0;
}

以上程序的结果是多少?2 和5?其实不是,是2和0。这个错误的结果是由形参与实参的类型不一致导致的。形参为int的指针变量,pdate[0]和pdate[1]分别占用4个字节,赋值后,pdate[0] = 2,pdate[1] = 5,而实参为short int的数组,传参时实际buf[0]是占用pdate[0]的前面两个字节,即buf[0] = 2, buf[1]是占用pdate[0]的后面两个字节,即buf[1] = 0。

例子2如下

#include<stdio.h>
#include <sys/select.h>

int add(short *date)
{
	*date = 3;
}

int main()
{
	int var ;
	add(&var);
	printf("var = %d\n",var);
	
	return 0;
}

以上程序的结果是多少?是3?其实不是,是一个随机数,形参为short 型的变量,占两个字节,实参为int型的变量,占四个字节,传参时,实际是实参的前两个字节传给形参,即实参的前两个字节是等于形参的值,后面两个字节是保留初始值,正常情况下,没有初始化的定义,系统默认置0,但并非是所有平台都会给没有初始化定义的变量置0,有些平台是给随机数。所以最终的结果不一定等于3。所以定义任何变量的时候一定要有初始化值,不然发生意想不到的错误。

2、值传递与地址传递的区分不清
值传递是把实参的值赋值给行参, 那么对行参的修改,不会影响实参的值 。
地址传递,是传值的一种特殊方式,他传递的是实参的地址,不是实参的值 那么对行参的修改,会影响实参的值 。
例子1

#include<stdio.h>
#include <sys/select.h>

int swap(int a , int b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
	return 0;
}

int main()
{
	int a = 10 , b = 20;
	swap(a,b);
	printf("a = %d\n",a);
	printf("b = %d\n",b);
	
	return 0;
}

以上程序的原本用途是想实现两个值之间的交换,但代码用的是值传递,所以形成的改变是无法改变实参,需要使用地址传递才行。
实现两个值之间的交换的正确代码

#include<stdio.h>
#include <sys/select.h>

int swap(int *a , int *b)
{
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
	return 0;
}

int main()
{
	int a = 10 , b = 20;
	swap(&a,&b);
	printf("a = %d\n",a);
	printf("b = %d\n",b);
	
	return 0;
}

例子2
通过进一步封住malloc,在封装函数内实现内存申请。

#include<stdio.h>
#include<stdlib.h>
#include<sys/select.h>

int malloc_inti(char *pdate)
{
	pdate = (char *)malloc(10);
	return 0;
}

int main()
{
	char *pdate = NULL;
	malloc_inti(pdate);
	printf("pdate = %p\n",pdate);
	return 0;
}

以上程序的结果是多少?是malloc正确分配的地址?其实不是,结果是NULL,函数传参是以值传递的形式,形参是指针变量,形参的改变是无法改变实参的值,即实参(指针变量)的值是没有变化的,所以结果为NULL。指针变量虽然存储的是一个地址,但也是一个变量
确定的做法是采用函数的地址传递的方式,代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<sys/select.h>

int malloc_inti(char **pdate)
{
	*pdate = (char *)malloc(10);
	if(*pdate == NULL)
	{
		printf("pdate pdate fail !\n");
		return -1;
	}
	return 0;
}

int main()
{
	char *pdate = NULL;
	malloc_inti(&pdate);
	printf("pdate = %p\n",pdate);
	return 0;
}

2、值传递与地址传递的应用
什么情况使用值传递?什么情况地址传递?
如果想要使形参对实参有影响的,就一定使用地址传递,如果想要形参对实参没有影响的,使用值传递或者地址传递都可以。但这涉及到两个问题
1、效率问题
2、函数栈空间占用问题
值传递是会拷贝一份到函数栈,如果参数大,拷贝需要占用点时间,并且会占用一定的函数栈空间。
地址传递是以指针的形式传给函数,通过指针操作即可,效率高,并且占用空间不大。但容易修改实参的值,加上const,就可以防止形参的操作对实参的改变。

以下为值传递的例子

#include<stdio.h>
#include<stdlib.h>
#include<sys/select.h>

struct stu
{
	....
	....
	....
}student

int module_inti(struct stu pdate)
{
	....
	....
	return 0;
}

int main()
{
	malloc_inti(student);
	return 0;
}

以下为地址传递的例子

#include<stdio.h>
#include<stdlib.h>
#include<sys/select.h>

struct stu
{
	....
	....
	....
}student

int module_inti(const struct stu *pdate)
{
	....
	....
	return 0;
}

int main()
{
	malloc_inti(&student);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值