1.标识符的作用域和可见性
一、作用域(生效范围)
局部作用域一定包含在全局作用域当中。
(1)空间角度
全局作用域:从定义开始到.c文件结束后终止。可以代替函数的参数传参,但全局变量会导致耦合性过高。
局部作用域
(2)时间角度:
变量的生存期。变量从开辟空间到把该空间被销毁掉的这段时间。分为动态生存期和静态生存期。
- 静态生存期:某个变量的生存期与程序运行的生存期相同。例如:全局变量,static关键字修饰的局部变量(会把动态变量转变为静态变量放到静态区)。
- 与程序的生存期间不同。例如:栈区上的变量
例:若没有全局变量的定义,add函数内会报错。
全局变量g_i在全局区或静态区,在上述两个区内的变量若未被初始化(.bss段),则按位清0,故printf打印出的值为0。
主函数定义之前:i就被定义好了,i有局部作用域同时具有静态生存期,
输出i的值为0
二、可见性
在程序运行到某一点时是否可见。
三、作用域与可见性的四条小真理
- 标识符必须先定义再使用。
- 同一作用域中不得出现同名标识符。
3.在没有包含关系的不同作用域中定义的同名标识符互不影响。
4.在两个或多个具有包含关系的作用域中定义的同名标识符,外层标识符在内层不可见。
输出值为:100;
2.关键字
- )auto关键字
auto关键字修饰的变量开辟和销毁是自动的,无需操心。你不写 类型名前也会默认有auto
2、)register 关键字
寄存器变量,修饰变量不能取地址.register关键字更像是一种建议,i不一定放在寄存器之中。
如:register int i;所开i空间开辟到寄存器中。寄存器在cpu中,比正常在栈区开辟的执行速度更快。
3、)extern关键字
extern后+类型名+变量名+ = 算声明不算定义。它真正定义的变量不在main.c里。
extern int a = 10;(错误)声明的同时不能初始化。
4、)static关键字
全局变量or static修饰的函数。
第九章 预处理命令
程序执行:编辑->预处理->编译 .c->链接->运行
9.1 宏定义
1.宏名通常所有字母都大写,以便与变量名区分。
2.宏定义后没有符号。
3.宏定义相当于无脑文本粘贴替换。
4.宏可以层层替换
输出:630
宏只有名字没有内容,只是定义一下有这个东西。为后续学习的条件编译做准备工作。
C语言会提供几个宏。
算有几行
输出文件名
(gcc -E -omain.i main.c)给main.c文件只预处理,把预处理之后的结果输入到main.i里。
带参宏:
编译器编译的是这个。
注意:带参宏不是函数
函数的调用有保护现场和恢复现场的过程。带参宏没有这个功能。带参宏的优点是效率高,但代码复用性降低。
9.2 文件包含名
1)绝对路径 “”和<>没区别
2)Include就是去打开<> “”内的文件去调用函数
3)“” 当前文件.c所在的目录路径
4)<>user目录下所在的路径
5)自己写是函数内包自己的头文件“”(能包在原文件的最好包进原文件里)
注意:变量的声明也放在头文件里,只放类型不放值。
9.3条件编译(无脑文本替换)
(1)#if (表达式)
文本
#endif
中间文本是否在预处理阶段作为有效代码被替换,取决于if后的表达式是否为真。
2)程序段1是否可以执行取决于 #ifdef后的标识符是否在之前被宏定义过。(类似:#define K)
用于调试程序较多。
(3)#ifndef 与ifdef逻辑相反。
可以解决多文件操作过程中对一个头文件中重复包含相同标识符
解决方法:在所有头文件编写时,先写:
#ifndef 文件名
#define 文件名
中间填
#endif(放最后)