函数回顾
类型名 函数名(参数列表)
{
函数体
}
类型名实际作用就是指定函数的返回值类型,函数在主函数中的作用主要体现在其有返回值。
默认返回0表示函数代码无错误,若函数确实不需要返回值,则可用void代替类型名,旨在告诉计算机这个函数不用返回值。
形参和实参
这两个参数呢,就相当于去占座,把包放在座位上,告诉大家这里会有人,但是是谁大家是不知道的。
举个栗子:
#include<stdio.h>
int Find_Max(int x,int y)/*这里的所有x,y均为形参,作用是告知用户该函数有两个int类型的参数*/
{
if(x>y) return x;
else return y;
}
int main()
{
int m,n; /*这里的输入才是实参,可以直接调用函数进行运算*/
printf("input two numbers:");
scanf("%d %d",&m,&n);
printf("max = %d",Find_Max(m,n));
return 0;
}
形参出了函数啥也不是。
传值和传址
传值就很简单了,上述栗子就是传值。
接下来介绍传址:(栗子2)
#include<stdio.h>
void swap(int*,int*);
void swap(int* x,int* y) /*做形参的是int类型地址*/
{
printf("before: %d %d\n",*x,*y);
int temp;
temp = *x;
*x = *y;
*y = temp;
printf("after:%d %d\n",*x,*y);
}
int main()
{
int m = 3,n =4;
printf("before: %d %d\n",m,n);
swap(&m,&n); /*像形参传递的是m,n的地址*/
printf("after:%d %d",m,n);
}
输出:
before: 3 4
before: 3 4
after:4 3
after:4 3
相反若代码将指针去掉,则输出变为:
before:3 4 /*函数内部*/
before:3 4
after:4 3/*函数内部*/
after:3 4
原因:每个函数的内部都是相互独立的,他们之间的功效只在自身函数内部适用,也就是说哪怕把m,n换为x,y也是不冲突的。(作用域不同)
但 是,若用到指针,我们看栗子2,我们向函数传递的是指向m,n的指针,对于指针呢我们知道孩子存储的是元素的地址,在计算机处理数据过程中每个数据都有一个固定的地址,我们通过对他解引用找到其中元素。我们将实参地址传递给形参地址,地址呢,一个地址只能有一个,此时实参地址直接代替了形参地址,在完成各种操作后,我们再对实参地址进行解引用,得到的就是交换后的结果(注:一遍没读明白建议读两遍,两遍没明白读三遍,很简单的,放轻松)
传数组
再次举栗子(栗子3):
#include<stdio.h>
void Get_Array(int a[10]);
void Get_Array(int a[10])/*好像是十个元素,但实际不过是a[0]的地址*/
{
int i;
a[9] = 1024;
printf("Get_Array:");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int i;
printf("main:");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
Get_Array(a);
printf("main.2:");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
return 0;
}
输出:main:0 1 2 3 4 5 6 7 8 9
Get_Array:0 1 2 3 4 5 6 7 8 1024
main.2:0 1 2 3 4 5 6 7 8 1024
这与栗子2中不同,好像这里的函数内部和主函数并不是独立的。Why???
其实很好理解:我们知道编译器在引用数组结构时直接引用的并不是整个数组,而是首字符的地址,也就是说,我们完全可以将这种情况类比为栗子2,我们向形参传递的是地址,而不是数值。就是这样。
可变参数
#include<stdarg.h>
-va_list
-va_start
-va_arg
-va_end
#include<stdio.h>
#include<stdarg.h>
int sum(int n,...)/*...说明参数个数不确定,其中n表示参数个数*/
{
int i,sum =0 ;
va_list vap;/*定义参数列表*/
va_start(vap,n);/*开始*/
for(i=0;i<n;i++)
{
sum+=va_arg(vap,int);/*获取后面每一个参数的值 int表示每个参数类型*/
}
va_end(vap);/*结束*/
return sum;
}
int main()
{
int result;
result = sum(3,1,2,3);/*3个int类型的参数*/
printf("%d\n",result);
printf("%d\n",sum(5,1,2,3,4,5));
return 0;
}
/*输出:6
15*/
所谓可变参数就是参数未事先确定,可根据用户输入随机应变。