程序设计与C语言学习笔记_第十章编译预处理与位运算

10章 编译预处理与位运算

编译预处理,是指源程序被正式编译之前所进行的处理工作。由预处理程序实现,负责分析和处理行首以‘#’开头的控制行,包括宏代换、文件包含和条件编译。

10.1 宏定义

宏定义就是把一长串字符序列用一个简短的名字去代替,这个名字称为宏名,被代替的长串序列就被称为宏值。

1. 简单宏

1) 定义格式:#define <宏名> <宏值>

2) 功能:将宏名代替宏值

3) 需要注意的问题:

(1) 宏名一般使用大写

(2) 如果宏名过长,可以使用需行符“\”

(3) 宏值为表达式时,最好用圆括号括起来

(4) 宏定义可以嵌套

(5) 若宏名出现在字符串中,则字符串中的宏名不作替换。

(6) 宏取消命令:#undef <宏名>

2. 带参数的宏

1) 定义格式:#define <宏名> <宏值(含参数的字符串)>

2) 功能:类似于函数

3) 需要注意的问题:

(1) 宏值中间的参数要用括号括起来。

(2) 当一个宏名要在另一个宏定义的宏值中出现时,最好将它的宏值部分括起来,以避免发生意外。

(3) 带参宏与函数的区别

[1] 函数调用时先对参数表达式进行计算,把计算的结果作为一个值去代替形参,而宏代换时不对参数求值。

[2] 函数的形参和实参的有类型,而宏的参数没有类型。

[3] 函数调用是在运行时处理的,要占有运行时间,而宏是在编译预处理阶段处理的,不占有运行时间。因此一些小的、调用次数频繁的函数,最好用带参的宏去代替。

10.2 文件包含

1. 一般格式:#include <文件名>|”文件名

2. 功能:用指定文件的一份拷贝和取代这条预处理。

3. 需要注意的问题

1) <>括起来的文件,预处理程序会在标准库头文件中去查找;””括起来的文件,预处理程序会在当前正在编译的程序所在目录中查找。

2) 文件包含可以嵌套,被包含文件里包含的文件也被包含文件所包含。

3) 被包含文件的全局变量也是包含文件中的全局变量。

10.3 条件编译

一个程序中的所有语句并不一定要全部编译执行,根据一定的条件可以对其中的一部分进行编译。能够控制编译范围的指令就是C语言提供的条件编译指令。

1. #if…#endif形式

1) 一般格式:

#if <常整数表达式>

<程序段>

#elif

<程序段>

#endif

2) 功能:若常整数表达式的值为真,则编译程序段。

3) 需要注意的问题

(1) 常整数表达式中只能出现预定于的常量标识符、整常数、字符常数等。

2. #ifdef…#endif形式

1) 一般格式:

#ifdef <标识符>

<程序段>

#endif

2) 功能:如果标识符用#define定义过,则编译程序段。

3. #ifndef…#endif形式

1) 一般格式:

#ifndef <标识符>

<程序段>

#endif

2) 功能:如果标识符未被#define定义过,则编译程序段。

4. 条件编译的主要用途:

1) 忽略程序的某一部分:

#if 0

<不编译的程序段>

#endif

2) 帮助程序调试

10.4 位运算

10.4.1 位运算

1. 字符逻辑运算符

1) 按位与运算符&

2) 按位或运算符|、

3) 按位取反运算符~

4) 按位异或运算符^(相同则为0,相反则为1)

5) 需要注意的问题:

(1) 任何一个数和它自身的异或永远是0,而任何一个数和0的异或的结果是其自身。

(2) 对一个数据用另一个数据进行两次异或操作后,将恢复这个对象原来的值。可用作加密工作。

(3) 按位与运算&用于选取一个数的某些二进制位。

(4) 按位异或运算|用于将一个数指定位置变成1。

(5) 按位异或运算^用于将一个数的指定位翻转,其它位不变。

(6) 对两个长度不等的数进行位运算时,右边对齐,短的数左边添0(整数/无符号数),或添1(负数)。

2. 字位移位运算符<<和>>

1) 调用格式:<数值> <<(左移位数)| <数值> >> (右移动位数)

2) 功能:将数值的二进制位数,向左或右移动指定位数。

3) 需要注意的问题:

(1) 对于整数或无符号数,左移运算中,若移掉的位中无1,则左移n位后的值是原值的2n倍。右移运算中,若移掉的位中无1,则右移n位后的值是原值的1/2n倍。

(2) 对于有符号数,在向左移时,得到的结果有可能是正数或负数;在向右移动时,分为逻辑右移和算术右移动,算术右移会保证数组的正负性不变。

10.4.2 与位运算有关的符合赋值运算符

你可能感兴趣的:(C/C++)