内部函数与外部函数
C语言程序的基本构成单位是函数,多源程序文件构成的程序中,函数的定义和调用也必须考虑可以调用的程序范围问题。
函数本质是全局的,定义函数的目的就是被其他函数调用。如果不回声明的话,一个源程序文件中定义的函数既可以被本文件中的其它函数被调用,也可以被其它源程序文件中的函数调用。根据函数能否被其他源程序文件调用,可以把函数分为内部函数和外部函数。
1. 内部函数
如果一个函数只能被其所在的源程序文件中其它的函数调用,则称为内部函数。定义内部函数时,在函数头的前面加上static关键字
代码语言:javascript复制static 类型标识符 函数名(形式参数列表)
{
}
2. 外部函数
如果在定义函数时,在函数头的前面使用extern关键字进行说明,则函数为外部函数。可以供其他源程序文件中的函数调用,一般形式如下:
代码语言:javascript复制extern 类型标识符 函数名(形式参数列表)
{
}
例如:
代码语言:javascript复制extern void process(int a, int b)
{
……
}
C语言规定,如果在定义函数时没用使用static或extern关键字说明,则函数默认为外部函数,即相对于使用了extern说明。
在需要调用外部函数的其它源程序文件中,需要对被调用的函数进行使用extern关键字进行原型说明。例如:extern void process(int a,int b);
编译预处理
C语言的编译预处理命令主要包括:宏定义、文件包含和条件编译。预处理命令均以“#”开始,命令的结尾没有分号,每条预处理命令必须占用单独一行。
1.宏定义
(1) 无参宏定义
无参宏定义的一般形式如下:
代码语言:javascript复制 #define 宏名 字符序列
如果源程序中使用了宏定义,编译预处理过程中,自动把源程序中出现的所有“宏名”替换为“字符序列”,这是一个纯文本替换,也称为宏替换。
例如下面定义了3个无参宏名:
代码语言:javascript复制 #define PI 3.14
#define R 10
#define AREA PI*R*R
(2) 有参宏定义
有参宏定义的一般形式如下:
代码语言:javascript复制 #define 宏名(参数表) 字符序列
有参宏定义在进行宏替换时,源程序出现宏名的地方都使用字符序列替换,替换时使用宏引用中的实参去替换宏定义中的形参。
例如,如下定义了一个有参的宏名。
代码语言:javascript复制 #define MUL(a,b) (a)*(b)
源程序中可以使用如下语句使用有参的宏:
代码语言:javascript复制 int x=3, y=4, z;
z=MUL(x,y);
注意:通常需要在有参宏定义时,字符序列中参数要加上圆括号,以免进行宏替换时出现错误,如z=MUL(x 3,y-1)*10,进行宏替换后的语句为:z=x 3*y-1*10;。
(3) 文件包含
文件包含也是一种编译预处理命令,其作用是把被包含的文件的内容全部引入到使用文件包含命令的源程序文件中。文件包含命令有以下2种形式:
代码语言:javascript复制#include <文件名> 或 #include "文件名"
文件包含命令使用尖括号形式时,编译器在系统默认的路径中寻找被包含文件;使用双引用形式时,编译器先在用户程序的当前工作目录中寻找被包含文件,如果找不到文件,再去系统默认的路径中寻找文件。
下面是几个文件包含命令的例子:
代码语言:javascript复制#include <stdio.h> //包含系统预定义的头文件
#include "user.h" //包含自定义的头文件
#include "func.c" //包含自定义的源程序文件
(4)条件编译
通常情况下,源程序文件中的所有语句行都需要参与编译,并生成到目标文件中。如果源程序需要根据特定的条件决定一部分源代码是否参加编译,则需要使用条件编译预处理命令。
C语言的条件编译预处理指令主要有三种形式。
1、#if指令
一般形式:
代码语言:javascript复制#if 表达式
程序段1
#else
程序段2
#endif
2、#ifdef指令
一般形式:
代码语言:javascript复制#ifdef 宏名
程序段1
#else
程序段2
#endif
3、#ifndef指令
一般形式:
代码语言:javascript复制#ifndef 宏名
程序段1
#else
程序段2
#endif