使用C/C++编译预处理时需要注意的问题

1、宏定义不是C/C++语句,不需要使用语句结束符“;”,否则它也被看做宏体的一部分。

2、不要在引用宏定义的参数列表中使用增量和减量运算符,否则将导致变量的多次求值。例如:

#define SQUARE(x) ((x) * (x))
int n1 = 5;
int m1 = SQUARE(n1++);			//m1 = 25,n1 = 7

int n2 = 5;
int m2 = SQUARE(++n2);			//m2 = 49,n2 = 7

3、带参数的宏体和各个形参应分别用括号括起来,以免造成意想不到的错误。例如:

#define SQUARE(x) x * x
int m = SQUARE(3 + 5);			//将被扩展为m = 3 + 5 * 3 + 5

4、当不再使用某一个宏时,可以使用#undef来取消其定义,否则简单地删除宏定义会带来许多编译错误。

5、编译伪指令#error用于输出与平台、环境等有关的信息。例如:

#if !defined(WIN32)
#error ERROR: Only Win32 Platform supported!
#endif
#ifndef _cplusplus
#error ERROR: MFC requires C++ compilation!
#endif

当预处理器发现应用程序中没有定义宏WIN32或者cplusplus时,把#error后面的字符序列输出到屏幕后即终止,程序不会进入编译阶段。

6、当需要暂时放弃一段代码的时候,如果这段代码本身就含有块注释时,使用块注释屏蔽它就比较麻烦,此时可使用条件编译伪指令#if来屏蔽这段代码。例如:

#if 0
…//希望屏蔽的代码
#endif

注意:由于条件编译由编译预处理器来处理,显然预编译伪指令无法计算有变量参与其中的表达式或sizeof表达式,只能用常量表达式。

7、编译伪指令#pragma用于执行语言实现所定义的动作,例如:

#pragma pack(push, 8)		/*对象成员对齐字节数*/
#pragma pack(pop)
#pragma warning(disable:4069)	/*不要产生第C4096号编译警告*/

8、构串操作符#只能修饰带参数的宏的形参,它将实参的字符序列(而不是实参代表的值)转换成字符串常量。例如:

#define STRING(s)   #s #s #s
#define TEXT(s)		"class" #s "Infor"
int abc = 100;
STRING(abc)			//展开为abcabcabc
TEXT(abc)			//展开为classabcInfor

注意:无论#s之间有多少个空格展开后都将忽略。

9、合并操作符##将出现在其左右的字符序列合并成一个新的标识符(注意,不是字符串)。例如:

#include <stdio.h>
#define paster( n ) printf( "token"#n" = %d\n", token##n )

int main(void)
{
	int token9 = 100;
	paster(9);			//输出token9 = 100

	return 0;
}

注意:(1)C语言字符串中的两个相连的双引号会被自动忽略;(2)使用合并操作符时,产生的标识符必须预先有定义,否则编译器会报“标识符未定义”的编译错误。

时间: 2024-10-09 23:31:44

使用C/C++编译预处理时需要注意的问题的相关文章

C预编译, 预处理, C/C++头文件, 编译控制,

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征.依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的. 其格式一般为: #Pragma Para 其中Para 为参数,下面来看一些常用的参数. (1)message 参数. Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输

Verilog学习笔记基本语法篇(十二)&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183; 编译预处理

h Verilog HDL语言和C语言一样也提供编译预处理的功能.在Verilog中为了和一般的语句相区别,这些预处理语句以符号"`"开头,注意,这个字符位于主键盘的左上角,其对应的上键盘字符为"~",这个符号并不是单引号"'".这里简单介绍最常用的`define `include `timescale. 1)宏定义`define 用一个指定的标识符(名字)来代表一个字符串,其的一般形式为: `define 标识符(宏名) 字符串(宏内容) 如:

第八章 编译预处理

编译预处理指令 (1)宏定义 (2)条件编译 (3)文件包含 宏定义 宏定义是指将一个标识符(又称宏名)定义为一个字符串(或称替换文本).在编译预处理时,对程序中出现的所有宏名都用相应的替换文本去替换,这被称为"宏替换"或"宏展开".C语言中,"宏定义分为无参宏定义和带参宏定义两种. 无参宏定义 #define 标识符 替换文本 #define 表示该语句行是宏定义命令 标识符 所定义的宏名,习惯上用大写字母表示 替换文本 可以是常量.关键字.表达式.语句

条件编译及编译预处理阶段分析与总结--笔记

C语言条件编译及编译预处理阶段分析与应用总结 (笔记) 一.C语言由源代码生成的各阶段如下: C源程序->编译预处理->编译->优化程序->汇编程序->链接程序->可执行文件 其中 编译预处理阶段,读取c源程序,对其中的伪指令(以#开头的指令)和特殊符号进行处理.或者说是扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器.预处理过程先于编译器对源代码进行处理. 在C 语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件.定义宏.根据条件决定编译

编译预处理和动态存储分配(1)

1 编译预处理 C语言中,凡是以“#”号开头的行,都称为“编译预处理”命令行.C语言的预处理命令有:#define, #undef, #include, #if, #else, #elif, #endif, #ifdef, #ifndef, #line, #pragma, #error. 1.1 宏替换 1.1.1 不带参数的宏定义 (1)不带参数的宏定义命令行形式如下: #define 宏名 替换文本 在#define.宏名和宏替换文本之间用空格隔开.例如: #define SIZE 100

C++的编译预处理

C++中,在编译器对源程序进行编译之前,首先要由预处理对程序文本进行预处理.预处理器提供了一组预编译处理指令和预处理操作符.预处理指令实际上不是C++语言的一部分,它只是用来扩充C++程序设计的环境.所有的预处理指令在程序中都是以"#"来引导,每一条预处理指令单独占用一行,不要用分号结束.预处理指令可以根据需要出现在程序的位置. 先来看看一些预处理指令 C++提供的编译预处理功能主要有以下三种: ① 宏定义 ② 文件包含 ③条件编译 首先是宏定义: C++ 宏定义将一个标识符定义为一个

程序结构~编译预处理和宏

/*            #define    #define<名字><值>    注意没有结尾的分号,因为不是C的语句    名字必须是一个单词,值可以是各种东西    在C语言的编译器开始之前,编译预处理程序    (cpp)会把程序中的名字换成值        完全的文本替换 宏    如果一个宏的值中有其他的宏的名字,也会被替换的    如果一个宏的值超过一行,最后一行之前的行末需要加\    红的值后面出现的注释不会被当做宏的值的一部分 *//*        没有值得

编译mysql时,到一半的时候报错,c++死掉

编译mysql时,到一半的时候报错,c++死掉,因为内存太小导致,创建交换分区或者增加内存重新编译. 设置2G交换分区来用下 : # dd if=/dev/zeroof=/swapfile bs=1k count=2048000 --获取要增加的2G的SWAP文件块 # mkswap/swapfile     -- 创建SWAP文件 # swapon/swapfile     -- 激活SWAP文件 # swapon -s            -- 查看SWAP信息是否正确 # echo"/v

黑马程序员-C学习笔记-编译预处理指令

------- ios培训. android培训.java培训.期待与您交流! ---------- 一.编译预处理指令 源代码 -> 编译预处理 -> 编译 -> 链接 -> 运行 编译预处理指令:在编译前进行解析处理的指令 特点:所有编译预处理指令都以#开头 所有编译预处理指令都不加分号 二.宏定义 1.不带参数的宏定义:  #define 宏名 值 (1)在预编译的时候所出现宏名标识的地方都会被替换成宏名后面的值 注意点:注释中的宏名不会被替换 在字符串中出现的宏名不会被替换