7、函数和作用域

函数

函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的,但在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。

函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。

C 标准库提供了大量的程序可以调用的内置函数。例如,函数 strcat() 用来连接两个字符串,函数 memcpy() 用来复制内存到另一个位置。

函数还有很多叫法,比如方法、子例程或程序,等等。

库函数和自定义函数

C语言在发布时已经为我们封装好了很多函数,它们被分门别类地放到了不同的头文件中(暂时先这样认为),使用函数时引入对应的头文件即可。这些函数都是专家编写的,执行效率极高,并且考虑到了各种边界情况。

C语言自带的函数称为库函数(Library Function)。库(Library)是编程中的一个基本概念,可以简单地认为它是一系列函数的集合,在磁盘上往往是一个文件夹。C语言自带的库称为标准库(Sdandard Library),其他公司或个人开发的库称为第三方库(Third-Party Library)。

库函数

标准C语言(ANSI C)共定义了15 个头文件,称为“C标准库”,所有的编译器都必须支持,如何正确并熟练的使用这些标准库,可以反映出一个程序员的水平。

可根据需要查阅C语言函数手册,网址是http://www.cplusplus.com/reference/clibrary/

main函数

C 语言有两种可能的运行环境中,它们之间有一定差别:

main函数一般有三种定义方式

//这两种定义方式都符合 C 语言标准
int main( void ) { /* … */ }
int main( int argc, char *argv[ ] ) { /* … */ }
//除此之外,许多 C 的实现版本还支持第三种、非标准语法的定义方式
int main( int argc, char *argv[ ], char *envp[ ] ) { /* … */ }

返回值

main()函数都会把最终的执行状态以整数的方式传递给操作系统。返回值如果是 0EXIT_SUCCESS,就表示程序执行过程一切顺利;任何非 0 的返回值,尤其是 EXIT_FAILURE,则表示程序执行时出现了某种问题。

头文件 stdlib.h 中定义了上述的两个常量 EXIT_SUCCESSEXIT_FAILUREmain()函数不一定要有 return 语句。如果程序运行到 main()函数块的右括号(}),那么就会自动向执行环境返回状态值 0。

main()函数结束等效于调用标准库函数 exit()main()的返回值作为 exit()的参数。

参数

函数的定义

return_type function_name( parameter list ){
   body of the function
}

函数的声明

所谓声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上

return_type function_name( parameter list );
//因为函数的参数名不是必须的,所以下面两种声明方式都可以
void max(int a,int b);
void max(int,int);

函数声明给出了函数名、返回值类型、参数列表(重点是参数类型)等与该函数有关的信息,称为函数原型(Function Prototype)。函数原型的作用是告诉编译器与该函数有关的信息,让编译器知道函数的存在,以及存在的形式,即使函数暂时没有定义,编译器也知道如何使用它。

有了函数声明,函数定义就可以出现在任何地方了,甚至是其他文件、静态链接库、动态链接库等。

#include<stdio.h>
//函数的声明
int max(int,int);

int main(){
   int num1 = 10;
   int num2 = 20;
   //调用函数
   printf("num1、num2最大值为:%d",max(num1,num2));
}
//函数的定义
int max(int a,int b){
   return a > b? a : b;
}

作用域规则

任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。C 语言中有三个地方可以声明变量:

  1. 在函数或块内部的局部变量
  2. 在所有函数外部的全局变量
  3. 在形式参数的函数参数定义中

局部变量

在某个函数或块的内部声明的变量称为局部变量。它们只能被该函数或该代码块内部的语句使用。局部变量在函数外部是不可知的。

#include<stdio.h>

int main(){
   //局部变量a和b,只可以在main函数中使用
   int a = 10,b = 20;
   printf("a:%d,b:%d\n",a,b);

   return 0;
}

全局变量

全局变量是定义在函数外部,通常是在程序的顶部。全局变量在整个程序生命周期内都是有效的,作用域在整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件),任意的函数内部能访问全局变量。

#include<stdio.h>
//局部变量a和b,作用域是整个程序
int a = 10,b = 20;

int main(){
   
   printf("a:%d,b:%d\n",a,b);

   return 0;
}

形参

函数的参数,形式参数,被当作该函数内的局部变量,它们会优先覆盖全局变量。

#include<stdio.h>

int a = 10;

void test(int a){
   printf("%d",a);
}

int main(){
   test(50);
   //50
   return 0;
}

同名参数调用规则

C语言规定,在同一个作用域中不能出现两个名字相同的变量,否则会产生命名冲突;但是在不同的作用域中,允许出现名字相同的变量,它们的作用范围不同,彼此之间不会产生冲突。

参数默认值

局部变量被定义时,系统不会对其初始化,必须自行对其初始化

定义全局变量时,系统会自动对其初始化

正确地初始化变量是一个良好的编程习惯,否则有时候程序可能会产生意想不到的结果,因为未初始化的变量会导致一些在内存位置中已经可用的垃圾值。

全局参数默认值:

数据类型 初始化默认值
int 0
char ''
float 0
double 0
pointer NULL