简单学C——第七天

时间:2023-03-08 21:41:01
简单学C——第七天

函数

函数是C语言重要的组成部分,你现在,或者以后(如果C没什么变化的话)所写的任何一个C语言程序都是由一个一个的函数组合在一起的,当然,现在或许你只会在主函数 main中写一个小程序,那么在看了本篇文章后,我觉得自己编写多个函数在一个程序中运行肯定不是问题啦,对于理解C语言的模块化编程也有很大的帮助。

前面已经学过很多数据类型,如指针,数组,结构体,等数据类型,想想,在使用之前,我们首先需要进行什么操作? 没错,首先是定义。当然,使用函数之前也要先定义一个函数。下面给出如何定义:

类型说明符 函数名 (传递的参数类型 行参名...)

{

    //此处的内容与主函数 main()大括号的一样

}

想一想,上面的定义方式是否感觉很眼熟?

还记得你接触的第一个程序吧?它的核心部分就是

int main()

{

//内容

return 0;  

}


其实这就是一个主函数,每一个c语言程序的运行都需要它的存在。它的名称是被固定的,不可整改的,即 main,会发现,main后面的小括号里面什么也没有,这说明这个main函数是不带参数的,这也是我们经常使用的。当然main函数也可以带参数,形如 int main(int argc,char *argv[]) ,具体可参见:http://blog.csdn.net/cnctloveyu/article/details/3905720   

上面的定义格式中的类型说明符指明了函数的返回值类型(一般所写的main函数最后都有 return 0;这代表运行正常, 也可以省略,如果省略编译时会自动加上,所以main函数的返回值为 int ),如果没有返回值 需要加上 void 代表返回值为空。形如 void print(){} 现在这就表示定义了一个返回值类型为空的名称为print且没有形式参数的函数。下面我将使用到自己定义的print函数。

#include<stdio.h>
void print() //print函数的定义
{
printf("you are someone\n"); //语句
return ;
}
int main()
{
print();//在主函数中调用print函数
}

运行结果:

简单学C——第七天

假如没有在主函数中调用所写的print函数,程序也没错,但是print也就没用到了。了解一个程序的执行过程是很关键的一步,作为一个C语言程序的运行顺序,简单来说就是以main函数为出发点,从上到下是根本,然后跟着所写的语句执行这个顺序。

下面再写一个稍微复杂的程序:比较两个数a,b的大小,如果a大,输出a,如果b大,输出b。

#include<stdio.h> //
int Max(int c,int d) //Max函数的定义 //
{
//此时c的值等于a的值,d==b
//如果c比d大,Max的返回值为c,否则,返回值为d
if(c>d) //
return c; //
else //
return d; //7
}
int main()
{
int a,b,c;//
scanf("%d%d",&a,&b);//3
//将a的值穿给形式参数 c,将b的参数穿给d
//将Max的返回值,即a,b的最大值赋值给c
c=Max(a,b);//4 //
printf("%d\n",c);//输出c //
return ; //
}

(附加:外部函数应该写在什么位置?

一般来说,为了方便起见,把外部函数放在调用它的函数的上方,这样可以不用再在主函数中对其进行申明。如果要放在你想放的位置,则必须要在主函数中对这个函数申明,以上面的程序为例,申明Max函数,需要在主函数里面加上申明语句:int Max(int c,int d);c和d这两个标识符可以去掉

#include<stdio.h> //

int main()
{
int a,b,c;
int Max(int c,int d); //2
//Max函数的申明,这样可以把Max函数放在main函数的后面
//一般都把申明与数据的定义放在同一位置
//或者 int Max(int,int);
scanf("%d%d",&a,&b);//3
//将a的值穿给形式参数 c,将b的参数穿给d
//将Max的返回值,即a,b的最大值赋值给c
c=Max(a,b);//4 //
printf("%d\n",c);//输出c //
return ; //
}
int Max(int c,int d) //Max函数的定义 //
{
//此时c的值等于a的值,d==b
//如果c比d大,Max的返回值为c,否则,返回值为d
if(c>d) //
return c; //
else //
return d; //7
}

比较一下上面两个程序的区别)

上面的程序就实现了求两个数当中的最大值。程序的运行顺序为 程序中所标注的 1~10  ,重复代表有可能是重复当中的某一个。现在看看这两个程序,与最上面的程序相比是不是多了很多东西? 第二和第三个程序定义了一个Max函数,它有返回值,所以return后面接的是一个与这个返回值一致的某个数或者表达式,第一个程序,定义了返回值的类型为void类型,为空,所以没有返回值,没有返回值可以写作 return;或者空着不写这一语句. 另外可以看到我在main函数中定义了变量c,同时,在Max函数中我也定义了一个变量c,作为形参。不是说,程序中的变量名不能相同吗?其实,这和变量的作用域有关。变量分为 两种,全局变量和局部变量,全局变量即在函数外部定义的变量,局部变量是在函数内部定义的变量,前面可能没提到过,全局变量只需要在函数的外部定义一次,即能在其下方所有的函数中使用这个变量,而局部变量定义在函数的内部,只能在这一个函数中使用,如果其他的函数要用到它,需要进行参数的传递,1.通过值传递,2.通过地址传递 ,传递给需要用到的那个函数。

下面讲讲这两种传递吧

1.值传递

只能传递某些变量的数值到自定义的函数里面,而不能访问变量的地址,不能访问变量的地址就意味着不能在自定义的函数体里面对这个变量进行操作,前面所写的比较两个数的大小就用到了值传递,因为在这个地方我们只需要了解到a,b两个的值,就可以判断到底是a大还是b大,并不需要对a与b的值进行更改等操作。

然而,很多时候,我们并不是只是想知道某个变量的值,例如:给你两个数,让你交换两个数的位置,然后输出。看到这,你肯定会想这不是很简单的事吗!!于是你就写出了下面的这些程序:

way1

#include<stdio.h>
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d %d\n",b,a);
}

way2

#include<stdio.h>
int main()
{
int a,b,c;
scanf("%d%d",&a,&b);
c=a;
a=b;
b=c;
printf("%d %d\n",a,b);
}

相信上面的两个程序你能够写出来。当然它们也都是十分正确的。可是我现在讲的是关于函数参数的地址传递啊,所以在实现这个程序的同时,我还要求你用到函数,并且其参数是地址,想想吧,现在应该怎么做呢?

回想上一讲的内容,指针,指针不正可以存放地址吗,可以通过指针接收主函数中的变量的地址,然后传送到自定义的函数中去,之后,在自定义的函数中就可以访问到主函数中的地址了,能访问地址,就能对与地址对应的变量进行操作。

code:

#include<stdio.h>
void swap(int *p,int *q) //指针p,q作为swap函数的形参,分别接收来自主函数的a,b的地址
{
//此时 *p和在主函数中的a一样,只是名字不一样,*q同理
int c;
c=*p;
*p=*q;
*q=c;
return; //因为是无返回void型的函数,也可以直接去掉这一行
}
int main()
{
int a,b;
scanf("%d%d",&a,&b); //输入两个数
swap(&a,&b);//&为取地址符,这样就可以把a和b的地址作为函数的实参传递给swap函数
printf("%d %d\n",a,b);//输出a和b
}

上面的代码与前面写的两个代码的功能是完全一样的,只是上面的代码有助于理解内容,所以复杂化了。

如果你看懂了这个代码,你可能会想,用其他的方法能不能实现呢?难道一定要用到指针吗?

很多人容易犯的错误就是不通过地址传递,通过值传递就想实现这,那么,可以编写一下试试,

code:

#include<stdio.h>
void swap(int p,int q)
{
//交换p与q的值
int c;
c=p;
p=q;
q=c;
//此时p与q的值被交换了,但是a与b的值并没有被交换
return; //swap函数结束
}
int main()
{
int a,b;
scanf("%d%d",&a,&b);
swap(a,b);//把a与b的数值传递给swap函数,在swap函数中不能再次访问到a与b
printf("%d %d\n",a,b);//输出a和b,结果与输入的一样,并没有交换
return ;
}

当然把主函数中的printf("%d %d\n",a,b);删掉。然后再再swap函数中的return;上面加上一句printf("%d %d\n",p,q);。这样也能实现功能,但是这样和上面的第五个程序并没有本质的区别。

还有一个方法,记得前面提到的全局变量不。它的作用域是它的定义下面的所有的函数。

code

#include<stdio.h>
int a,b;//定义a,b为全局变量,作用于下面的所有函数
void swap()
{
//交换a和b
int c;
c=a;
a=b;
b=c;
return; //swap函数结束
}
int main()
{
scanf("%d%d",&a,&b);
swap();//无需传递参数,因为a与b一直都存在于main主函数和swap函数
printf("%d %d\n",a,b);
return ;
}

由于重复的代码比较多,所以就不放上运行结果了。可以自己粘贴运行一下。

这样也实现了相同的功能。因为a,b是全局变量,所以不用通过地址传递也能在swap中访问到a与b的地址

关于函数的就说这么多吧。虽然还有不少没提到,不过这也足够初学者去理解了。