0x00 主要内容
- 函数
- 作用域规则
- 预处理
0x01 函数
隐藏细节
函数定义
返回值类型 函数名(参数声明表) {
声明和语句
}
返回值默认类型为int
函数之间的通信可以通过参数、函数返回值以及外部变量进行
被调用函数通过return语句向调用者返回值,return后可跟任意表达式,必要时可加括号
调用函数可以忽略返回值
空参数列表使用void
定义函数返回类型
double atof(char []);
int mian(void) {
double atof(char []);
...
}
double atof(cahr s[]) {
...
}
0x02 外部变量
C 语言程序可以看做由一系列的外部对象构成,这些外部对象可能是对象或函数。
通过同一个名字对外部变量的所有引用实际上都是引用同一个对象,函数本身就是“外部的”。
外部变量可在全局范围内访问, 所有可用于函数间的数据共享。
外部变量与内部变量相比具有更大的作用域和更长的生存期。
0x03 作用域规则
C语言程序的函数与外部变量可以分开进行编译。一个程序可以存放在几个文件中,已编译过的函数可以从库中进行加载。
名字的作用域指程序中可以使用该名字的部分
- 自动变量: 作用域是声明该变量名的函数,不同函数可以有相同的变量名,参数也是自动变量
- 外部变量: 作用域从声明它的地方开始,到其所在的文件的末尾结束
外部变量的定义与声明
变量声明用于说明变量的属性(主要是变量的类型),而变量定义除此之外还将引起存储器的分配。
如果要在外部变量的定义之前使用该变量,或者外部变量的定义与变量的使用不在同一个源文件,必须在相应的变量声明中强制性使用关键字extern
。
在程序的所有源文件中,一个外部变量只能在某个文件中定义一次,其他文件可以通过extern
声明访问它。
外部数组变量的定义必须指定数组的长度,但extern
声明不一定要指定长度。
变量的初始化只能出现在其定义中。
0x04 头文件
解决定义和声明在在多个源文件之间的共享问题。
使用头文件时通过#include
包含进来。
0x05 静态变量
用static
声明限定外部变量与函数,可以将其后声明的对象的作用域限定为被编译源文件的剩余部分。
static类型的内部变量是一种只能在某个特定函数中使用但一直占据存储空间的变量。
0x06 寄存器变量
register
声明告诉编译器,尝试将变量保存在机器的寄存器中,这样可以使程序更小、更快。但编译器可以忽略次选项。
register声明只适用于自动变量以及函数的形式参数。
0x07 初始化
不显示初始化的情况下,外部变量和静态变量都将被初始化为0,自动变量和寄存器变量的初始值没有定义(无用信息)。
- 外部变量和静态变量: 初始化表达式必须是常量表达式,且只能初始化一次。
- 自动变量和寄存器变量:每次进入函数和程序块时初始化,初始化表达式可以不是常量表达式。
- 数组: 声明后紧跟一个大括号包括的初始化表达式列表,未被初始化的部分将被初始化为0。
- 字符:
cahr pattern[] = "ould";
等价于char patern[] = {'o', 'u', 'l', 'd'};
0x08 递归
函数可以直接或间接调用自己
0x09 C预处理器
预处理器是编译过程中单独执行的第一个步骤
- 文件包含:
#include 文件名
, 所在行将被替换为文件名指定的文件内容,引号表示在源文件所在位置查找该文件,如果没找到,或者文件名用尖括号括起来,则根据相应的规则查找该文件。 - 宏替换:
#define 名字 替换文本
, 后续所有出现名字记号的地方将被替换为替换文本。 - 条件包含: 使用条件语句对预处理本省进行控制
条件包含实例:
#if SYSTEM == SYSV
#define HDR "sysv.h"
#elif SYSTEM == BSD
#define HDR "bsd.h"
#elif SYSTEM == MSDOS
#define HDR "msdos.h"
#else
#define HDR "default.h"
#endif
#include HDR