3.预处理
define 宏定义
tips: 1.反斜杠作为接续符时,在本行其后面不能再有任何字符,空格都不行。 2.定义宏的时候一定要注意什么时候该用空格。 3.用 define 宏定义表达式不要吝啬括号,因为表达式是直接替换。 4.用宏开始或结束一段注释是不行的,因为注释先于预处理指令被处理。
文件包含
文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编 译,结果将生成一个目标文件。C语言提供 #include 命令来实现文件包含的操作,它实际是 宏替换的延伸,有两种格式: 格式 1: #include 其中, filename 为要包含的文件名称,用尖括号括起来,也称为头文件,表示预处理到 系统规定的路径中去获得这个文件(即 C 编译系统所提供的并存放在指定的子目录下的头 文件)。找到文件后,用文件内容替换该语句。 格式 2: #include “filename” 其中, filename 为要包含的文件名称。双引号表示预处理应在当前目录中查找文件名为 filename 的文件,若没有找到,则按系统指定的路径信息,搜索其他目录。找到文件后,用 文件内容替换该语句。 需要强调的一点是: #include 是将已存在文件的内容嵌入到当前文件中。 另外关于#include 的路径也有点要说明: include 支持相对路径,格式如 trackant(蚁迹寻 踪)所写: .代表当前目录, ..代表上层目录
#pragma once
只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。#error
预处理指令的作用是,编译程序时,只要遇到 #error 就会生成一个编译错误提示消息,并停止编译。#line 预处理
作用是改变当前行数和文件名称,它们是在编译程序中预先定义的标识符。
通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析#pragma pack & 内存对齐
为什么要内存对齐?
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。(字,双字,和四字在自然边界上不需要在内存中对齐。)
#pragma pack()来改变编译器的默认对齐方式
使用指令#pragma pack (n),编译器将按照 n 个字节对齐。
使用指令#pragma pack (),编译器将取消自定义字节对齐方式.
每个成员按自己的方式对齐.也就是说虽然指定了按 n 字节对齐,但并不是所有的成员都是以 n 字节对齐。
其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是 n 字节)中较小的一个对齐。即:min( n, sizeof( item )) 。并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。
首先,每个成员分别按自己的方式对齐,并能最小化长度。
其次,复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度。
然后,对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐。
# 预算符
#define SQR(x) printf("The square of x is %d.\n", ((x)*(x))); 如果这样使用宏: SQR(8); 则输出为: The square of x is 64. 引号中的字符 x 被当作普通文本来处理,而不是被当作一个可以被替换的语言符号 可以使用“ #”,它可以把语言符号转化为字符串。 #define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x))); 再使用: SQR(8); 则输出的是: The square of 8 is 64
## 预算符
#define XNAME(n) x ## n 如果这样使用宏: XNAME(8) 则会被展开成这样: x8
就是个粘合剂,将前后两部分粘合起来。