函数与程序结构

函数

函数定义

返回值类型 函数名(参数列表) {
	语句
	return 表达式;
}
1
2
3
4

函数定义可以以任意次序出现在一个或多个源文件中,但同一函数不能分割存放在多个文件中。

返回值类型可省略,默认为int

函数的类型由其参数以及返回类型共同决定。

函数原型

返回值类型 函数名(参数列表); 
1

函数原型的参数列表中的参数名是可选的。

外部变量

若变量定义在任何函数的外部,即为外部变量。

int extern_val = 10; // 外部变量的变量定义

void main() {
}
1
2
3
4

外部变量的作用域

外部变量的作用域:从声明它的地方开始,到其所在文件的末尾结束。

  • 若在同一个源文件中,且在变量定义后使用,则可以直接访问此外部变量。

  • 若在同一个源文件中,在变量定义前使用,则必须使用关键字extern声明该外部变量后,方可使用。

  • 若不在同一个源文件中,则必须使用关键字extern声明该外部变量后,方可使用。

extern int extern_val; // 外部变量的变量声明
1

外部变量的定义

定义变量的类型、变量名和值,会分配空间。

在一个程序的所有源文件中,一个外部变量只能在某文件中定义一次

只能在变量定义中对外部变量进行初始化。

外部变量的声明

说明变量的类型、变量名。

在其他源文件或同一源文件的变量定义之前访问此外部变量时,需要使用变量声明。变量声明无次数限制。

变量声明不可对外部变量进行初始化。

static

static 函数

函数名默认是全局可访问的。若用static声明某函数,则该函数只对其所在文件可见,其他文件无法访问。

static 外部变量

static 外部变量:只能被其所在的源文件使用。

static 内部变量

内部变量是:

  • 在函数中定义的变量;

  • 作用域是所在函数内;

  • 所在函数被调用时创建,退出函数时消失。

static 内部变量:与内部变量类似,主要不同是其生命周期是其所在函数被调用后创建,直到退出程序才消失实质上static就是使内部变量变得永生

void test_static_internal_val() {
    static int count = 0;
    printf("%d\t", ++count);
}

// 连续调用此函数5次的输出为:1 2 3 4 5
1
2
3
4
5
6

递归

递归:函数可以直接或间接地调用自身。

递归并不节省存储器的开销,因为递归调用过程中必须在某个地方维护一个存储处理值的栈。

递归的执行速度并不快,但代码比较紧凑,并且比相应的非递归代码更易于编写和理解。

C预处理器

文件包含

在源文件中,使用include指令包含头文件:

  • #include "文件名" // 先从当前源文件所在位置查找,后根据相应的规则查找系统头文件。

  • #include <文件名> // 根据相应的规则查找系统头文件。

被包含的头文件中也可使用include包含其他头文件。

宏替换

宏替换的格式为:#define 名字 替换文本

后续所有出现“名字”记号的地方都将被替换为“替换文本”。

#define forever for(;;)
	
forever {
    // 语句
}
1
2
3
4
5

“替换文本”可以是任意字符串。

“名字”的命名方式与变量名相同。

#define指令占一行。也可以把一个较长的宏定义分成若干行,在待续的行末尾加上反斜杠符\

#define swap(t, x, y) t tmp = x; \
    x = y; \
    y = tmp;
	
int a = 1;
int b = 2;
swap(int, a, b); // 交换a和b的值。
1
2
3
4
5
6
7

宏定义可以带参数。

#define max(A, B) ((A) > (B) ? (A) : (B))

max(5, 10)结果为10
1
2
3

可通过#undef 名字取消指定名字的宏定义。

条件包含

条件包含的相关指令:

指令 说明
#if if程序块的开始符,相当于if
#endif if程序块的结束符
#else 相当于else
#elif 相当于else if
#ifdef 判断指定宏名字是否已定义
#ifndef 判断指定宏名字是否仍未定义

#if#elif等后面接条件判断,不能包含sizeof、类型转换运算和enum。

在预处理过程中,根据条件计算所得值,选择性地包含不同的代码。

// 根据环境变量SYSTEM选择包含哪个版本的头文件
#if SYSTEM == SYSV
    #define HDR "sysv.h"
#elif SYSTEM == BSD
    #define HDR "bsd.h"
#else
    #define HDR "default.h"
#endif
	
#include HDR
1
2
3
4
5
6
7
8
9
10

使用条件包含保证同一头文件只被包含一次。

#if !define(MAIN)
#define MAIN
    // main.h的内容
#endif
1
2
3
4
#ifndef MAIN
#define MAIN
    // main.h的内容
#endif
1
2
3
4