C语言程序设计_中国大学MOOC(慕课)https://www.icourse163.org/course/ZJU-9001https://www.icourse163.org/course/ZJU-9001
12.1 全局变量
全局变量
- 定义在函数外⾯的变量是全局变量。
- 全局变量默认初始化为 0 或 NULL。
- 如果函数内部存在与全局变量同名的变量,则全局变量被隐藏。
静态本地变量
- 在本地变量定义时加上static修饰符就成为静态本地变量。
- 静态本地变量实际上是特殊的全局变量(它们位于相同的内存区域),但是它只能在本地访问。
- 本地变量、全局变量、静态变量的作用域和生存期如下。
tips
- 返回本地变量的地址是危险的。
- 不要使⽤全局变量来在函数间传递参数和结果。
- 尽量避免使⽤全局变量/静态本地变量(函数是线程不安全的)。
12.2 编译预处理和宏
编译预处理指令
- #开头的是编译预处理指令。
- #define⽤来定义⼀个宏。
#define
- #define <名字> <值>
- 在C语⾔的编译器开始编译之前,编译预处理程序会把程序中的名字换成值(完全的文本替换)。
- 注意没有结尾的分号,因为不是C的语句。
宏
- 如果⼀个宏的值中有其他的宏的名字,也是会被替换的。
- 如果⼀个宏的值超过一行,最后一行之前的行末需要加 \ 。
带参数的宏
- 宏可以带参数,像函数一样。(例如:#define cube(x) ((x)*(x)*(x)))
- 带参数的宏的原则:⼀切都要括号。
- 整个值要括号。
- 参数出现的每个地方都要括号。
- 错误示例:
- #define RADTODEG(x) (x * 57.29578)
- #define RADTODEG(x) (x) * 57.29578
- 正确示例:
- #define RADTODEG(x) ((x) * 57.29578)
12.3 大程序结构
多个.c文件
- ⼀个源代码文件太长了适合分成几个文件。
- ⼀个.c⽂件是⼀个编译单元,编译器每次编译只处理⼀个编译单元。
- 对于项目,Dev C++的编译会把⼀个项目中所有的源代码文件都编译后,链接起来。
头文件
- 把函数原型放到⼀个头文件(.h文件)中,在需要调⽤这个函数的源代码⽂件(.c⽂件)中#include这个头文件,就能让编译器在编译的时候知道函数的原型。
- 在使用和定义这个函数的地方都应该#include这个头文件。
- ⼀般的做法就是任何.c都有对应的同名的.h,把所有对外公开的函数的原型和全局变量的声明都放进去。
#include
- #include是⼀个编译预处理指令,和宏⼀样,在编译之前就处理了。
- 它把那个文件的全部⽂本内容原封不动地插⼊到它所在的地方。
- #include有两种形式来指出要插⼊的⽂件
- #include<>:插入标准库的头文件。
- #include "" :自己写的头文件。
- #include的误区:
- #include不是⽤来引⼊库的。
- stdio.h里只有printf的原型,printf的代码在另外的地方,某个.lib(Windows)或.a(Unix)。
- #include<stdio.h>只是为了让编译器知道printf函数的原型,保证你调⽤时给出的参数值是正确的类型。
不对外公开的函数/全局变量
- 在函数/全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的函数/全局变量。
声明
- 只有声明可以被放在头文件中。
- 变量的声明:
- int i; 是变量的定义
- extern int i; 是变量的声明
- 重复声明:同⼀个编译单元里,同名的结构不能被重复声明。(如果你的头文件里有结构的声明,很难这个头文件不会在⼀个编译单元里被#include多次,所以需要“标准头文件结构”)。
标准头文件结构
- 运用条件编译和宏,保证这个头⽂件在⼀个编译单元中只会被#include⼀次。