【C语言】04-函数

说明:这个C语言专题,是学习iOS开发的前奏。

也为了让有面向对象语言开发经验的程序猿,可以高速上手C语言。

假设你还没有编程经验。或者对C语言、iOS开发不感兴趣。请忽略

一、函数的分类

前面已经说过。C语言中的函数就是面向对象中的"方法",C语言的函数能够大概分为3类:

1.主函数,也就是main函数。每一个程序中仅仅能有一个、也必须有一个主函数。

不管主函数写在什么位置,C程序总是从主函数開始运行

2.开发者自己定义的函数,可有可无,数目不限

3.C语言提供的库函数,比如stdio.h中的输出函数printf()和输入函数scanf()

 

二、函数的声明和定义

虽说C中的函数类似于Java中的方法,但在使用上还是有差别的。

1.在Java中,每一个方法的定义顺序没有限制。在前面定义的方法内部能够调用后面定义的方法

复制代码
1 public void test() {
2      int c = sum(1, 4);
3  }
4  
5  public int sum(int a, int b) {
6      return a + b;
7  }
复制代码

第1行定义的test方法能够调用在第5行定义的sum方法

 

2.在标准C语言中,函数的定义顺序是有讲究的,默认情况下。仅仅有后面定义的函数才干够调用前面定义过的函数

复制代码
1 int sum(int a, int b) {
2      return a + b;
3  }
4  
5  int main()
6  {
7      int c = sum(1, 4);
8      return 0;
9  }
复制代码

第5行定义的main函数调用了第1行的sum函数,这是合法的。假设调换下sum函数和main函数的顺序,在标准的C编译器环境下是不合法的(只是在Xcode中仅仅是警告,Xcode中用的是GCC编译器)

 

3.假设想把其它函数的定义写在main函数后面,并且main函数能正常调用这些函数。那就必须在main函数前面作一下函数的声明

复制代码
 1 // 仅仅是做个函数声明,并不用实现
 2  int sum(int a, int b);
 3  
 4  int main()
 5  {
 6      int c = sum(1, 4);
 7      return 0;
 8  }
 9  
10  // 函数的定义(实现)
11  int sum(int a, int b) {
12      return a + b;
13  }
复制代码

我们在第2行做了sum函数的声明,然后在第6行(main函数中)就能够正常调用sum函数了。

函数的声明格式:

返回值类型  函数名 (參数1, 參数2, ...)

能够省略參数名称,比方上面的sum函数声明能够写成这样:

int sum(int, int);

仅仅要你在main函数前面声明过一个函数,main函数就知道这个函数的存在,就能够调用这个函数。到底这个函数是做什么用。还要看函数的定义。

假设仅仅有函数的声明。而没有函数的定义,那么程序将会在链接时出错。

 

4.在大型的C程序中,为了分模块进行开发,通常会将函数的声明和定义(即实现)分别放在2个文件里,函数声明放在.h头文件里,函数定义放在.c源文件里

以下我们将sum函数的声明和定义分别放在sum.h和sum.c中

sum.h文件

 

sum.c文件

 

然后在main.c中包括sum.h就可以使用sum函数

实sum.h和sum.c的文件名称不一样要同样,能够随便写,仅仅要文件名称是合法的

执行步骤分析:

1> 在编译之前。预编译器会将sum.h文件里的内容复制到main.c中

2> 接着编译main.c和sum.c两个源文件,生成目标文件main.obj和sum.obj。这2个文件是不能被单独运行的,原因非常easy:

sum.obj中不存在main函数,肯定不能够被运行

* main.obj中尽管有main函数,可是它在main函数中调用了一个sum函数,而sum函数的定义却存在于sum.obj中,因此main.obj依赖于sum.obj

3> 把main.obj、sum.obj链接在一起,生成可运行文件

4> 执行程序

 

讲到这里。有人可能有疑惑:可不能够在main.c中包括sum.c文件,不要sum.h文件了?

大家都知道#include的功能是拷贝内容,因此上面的代码等效于:

这么一看,语法上是绝对没有问题的。可是绝对执行不起来,在链接时会出错。

原因:编译器会编译全部的.c源文件,这里包含main.c、sum.c。编译成功后生成sum.obj、main.obj文件。当链接这两个文件时链接器会发现sum.obj和main.obj里面都有sum函数的定义。于是报"标识符反复"的错误。

 

有人可能认为分出sum.h和sum.c文件的这样的做法好傻B。好端端多出2个文件。你把全部的东西都写到main.c不就能够了么?

  • 没错,整个C程序的代码是能够都写在main.c中。可是,假设项目做得非常大。你能够想象得到,main.c这个文件会有多么庞大,会严重减少开发和调试效率。

  • 要想出色地完毕一个大项目,须要一个团队的合作,不是一个人就能够搞的定的。假设把全部的代码都写在main.c中。那就导致代码冲突,由于整个团队的开发者都在改动main.c文件。张三改动的代码非常有可能会抹掉李四之前加入的代码。

  • 正常的模式应该是这样:假设张三负责编写main函数,李四负责编写一系列的自己定义函数,张三须要用到李四编写的某个函数,怎么办呢?李四能够将全部的函数声明在一个.h文件里,比方lisi.h,然后张三在他自己的代码中包括lisi.h文件,接着就能够调用lisi.h中声明的函数了,而李四呢,能够独立地在另外一个文件里(比方lisi.c)编写函数的定义。实现那些在lisi.h中声明的函数。

    这样子,张三和李四就能够相互协作、不会冲突。

 

三、函数的形參和实參

定义函数时,函数名后面的()中定义的变量称为形式參数(形參)。在调用函数时传入的值称为实际參数(实參)。

复制代码
// b是test函数的形參(形式參数)
void test(int b) 
{ b
= 9; // 改变了形參b的值 } int main() { int a = 10; printf("函数调用前的a:%d ", a); test(a); // a是test函数的实參(实际參数) printf("函数调用后的a:%d", a); return 0; }
复制代码

假设是基本数据类型作为函数的形參。那是简单的值传递,将实參a的值赋值给了形參b。相当于

int a = 10;
int b = a;
b = 9;

a和b是分别有着不同内存地址的2个变量。因此改变了形參b的值。并不会影响实參a的值。

上述代码的输出结果为:

原文地址:https://www.cnblogs.com/blfbuaa/p/6936494.html