标签:
C源码在进行编译前会先经过预处理,预处理指令均以#开头,结尾没有分号(;)不是C语句。预处理器采用“语言符号”的分析方式,将空格作为区分标志之间的符号,一行作为一条指令,“\”可以将预处理指令延伸到下一行。
(1)不带参数的宏定义就是用一个标识符(宏名)来代表一个字符串。它的一般形式为
【#define Macro Str】
在预处理的时候程序中的宏名Macro被替换为字符串Str,这个过程称为宏展开。
(2)#define指令出现在程序中函数的外面,宏名的有效范围为该指令行起到本源文件结束或#undef。
(3)宏展开只是简单的字符串替换,简单宏常用于定义常量,宏没有类型,也没有优先级的概念,使用定义常量主要用于指定数组长度【#define ayyLength 256】,建议尽量使用const或enum代替宏定义常量【const int arrLen 256;】。建议不使用宏定义类型【#define Status int】而是用typedef关键字【typedef Status int;】。
(4)宏不是C语句不能加分号,否则会将分号一起代入。考虑到优先级问题,其中表达式也可能需要括号。
(5)宏代替的字符串可以是常量也可以表达式,格式描述符,语句(甚至是它们的一部分)等任何C程序中出现的字符串。 当然,宏代替的字符串中也可以包含已定义的宏名。
(6)
【#undef宏名】
#undef指令可以终止宏名的定义。
(1)
【#define Macro(argus) str】
对带参数的宏展开 是将带实参的宏 按照#define指令行中按从左到右的顺序进行置换。宏名和带参数的括号之间不能加空格,否则将成为无参数宏,空格后的每一个字符都将作为替代字符串的一部分。
(2)带参数的宏不是函数,它只是进行简单字符代换 。定义宏时参数和字符串可以是任意的,但在定义时要注意标识符不能出现重名【#define Macro(Macro) str】(利用代码块作用域)。在实际调用时参数可能是单个数据对象也可能是表达式,由于宏只进行简单文本代换考虑到优先级和结合性的问题,建议在定义宏时将参数用圆括号括起以作为一个独立单位。
(3)含参宏类似于inline函数,其调用也是采用传址的方式(真正的在调用点嵌入函数代码)。宏无类型,其参数也没有类型,只是一个符号代表,含参宏可以作为模板函数(C++引入,不同类型的参数可以使用同一段函数体)。
(4)宏与函数相比没有参数传递和返回值的限制使用更加自由灵活,而函数相对独立便于完成较复杂的任务。函数调用需较多时间处理内存等,而宏不需要。
(1)对程序作预处理前,编译器会进行翻译处理。编译器首先把源码中的字符映射到源字符集。然后编译器查找反斜线后紧跟换行符(这里指按下回车键在源码中产生的换行符而非转义字符‘\n‘)的实例并删除这些实例。所以反斜线加回车键可以将宏定义扩展到多行。
(2)#运算符与参数结合可以那参数名转换为相应字符串。例如:x是宏的形参,实参为1时#x将被替换为"1"(字符串),x将被替换为1(数值常量)。
(3)##运算符可以把两个语言符号组合成一个语言符号。例如:n是宏的形参,实参为1时,x##n将变为标识符x1,如果无##编译器将把xn当做一个语言符号,在宏参数中中无法找到于是不进行替换。
【 #include<文件名> 】或
【 #include"文件名" 】
条件编译使得程序中的一部分内容只在满足一定条件时才进行编译或不进行编译。
1.ifdef指令
【#ifdef Label
Block1
#else
Block2
#endif
】
若指定的标识符已经被#define指令定义过,则对程序段1进行编译否则对程序段2进行编译。可以用于程序调试等。
也可以用
【 #ifdef
Block
#endif
】
2.ifndef指令
【#ifndef Label
Block1
#else
Block2
#endif
】
与1正好相反,若标识符未被定义则编译程序段1,否则编译程序段2。
为了避免头文件重复包含,通常使用条件编译:
【 #ifndef STDIO_H
#define STDIO_H
...
#endif
】
3.if指令
【#if expr
Block1
#else
Block2
#endif
】
表达式为真时编译程序段1,否则编译程序段2。
不用条件编译指令而用if语句同样也可以实现,但是那样做目标程序长(所有语句都参加编译),运行时间长(在if语句处需进行逻辑判断)。
标签:
原文地址:http://www.cnblogs.com/Finley/p/5074589.html