A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 令狐冲 中级黑马   /  2015-12-1 20:00  /  900 人查看  /  2 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

1、预处理指令的概念及分类。
        1)预处理
        源代码在编译成机器指令之前,要进行预处理。预处理阶段可以根据预处理指令,(以#开头)执行 一些列操作。预处理可以在编译之前处理及修改C源代码。完成预处理阶段,并分析及执行了所有的预 处理指令之后,这些指令就不再出现在源代码中。编译器开始编译阶段,生成与程序对应的机器码。 咱们之前的所有列子都使用了预处理指令,如#include 和 #define 指令。include(包含) 我们之前学习过。
        2)替换程序代码
        程序在编译之前,预处理器指令会替换源代码中的符号。最简单的符号替换前面已经介绍过。列入使用预处理器指令将字符串PI替换为特定值: #define PI 3.14159265 。标示符PI 看起来像变量。 但是它不是变量,与变量一点关系也没有。PI是一个标志,作用在预处理阶段用来替换在#define指令中指定的一串数字。当预处理完成后,准备编译程序时,PI字符串已经被它的 定义取代。不再出现了。
        printf("%f",PI); 预编译是指令, 不到需要的时候 不要放语句结束符 ” ; “
       
2、宏的概念
        宏基于前面的#define指令,但它的适用范围比较大,不仅可以使用固定的字符串代替某些代码,可以进行参数化的代换,这个代换也叫宏展开或者宏代换。这样我们C语言中宏就可以分为两个类型了。一种是无参数宏,一种是有参数宏。二者在定义时的一般形式为:
        无参宏:#define 宏名 字符串
        有参宏:#define 宏名(形参表) 字符串

3、无参宏使用注意事项
        · 习惯上宏名也是标示符,用大写字母表示,以便与变量区别。但也允许用小写字母。 · 字符串可以是常量,表达式,格式串,数据类型等,写什么都会原封不动的替换掉。 · 分号,宏定义是指令,末尾不加分号。
        · 定义位置,作用域。定义必须写在函数外面,作用域为宏定义命令到源程序结束。
        · 终止作用域可以使用#undef命令。
        · 嵌套定义
        无参数宏定义 一般形式
                #define 宏名 字符串
        作用: 用宏名替换字符串,简化操作,降低编码错误。
        注意事项:
                1、宏名 : 标示符 一般为大写字母,便于跟不同的变量区分,
                2、字符串 :原封不动的替换,常量,表达式,格式字符串, 可以嵌套定义 作用域: 从定义位置开始,到源文件结束
                3、终止: #undef 命令终止。

4、有参宏
        1)有参宏定义
        带参宏 定义 的一般形式为:
                #define 宏名(形参表) 字符串
        在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。 参数列表中放形参,字符串中放置形参的操作。 对带参的宏,在调用中, 不仅要宏展开,而且要用实参去代换形参。
        调用形式:
                宏名(实参表);
        实例:
                #define W(y) y+1 printf("%d \n",W(3));
        2)有参宏使用注意事项 · 定义符合规范。如:        
                   形参之间可以出现空格,但是宏名和形参表之间不能有空格出现。
                · 形参只是简单的符号代换,不需要分配内存空间,不存在值传递问题。
                · 通常加括号利于代码的可读性。
                · 字符串可以放多个语句。
                · printf语句的定义为Log模式。
        #define Log(format,...) printf(format,## __VA_ARGS__)。这里,‘...’指可变参数。这类宏在被调用时,##表示成零个或多个参数,包括里面的逗 号,一 直到到右括弧结束为止。当被调用时,在宏体(macro body)中,那些符号序列集合 将代替里面 的__VA_ARGS__标识符。
                举例:
                #define SUM(a) a+a
                #define M1(x ,y) (x)*(y)+(x)+(y)
                #define M2(a) a+3*y
                #define M3(m,n) m = a+2;n=a*2;

5、#define和typedef的区别
        应注意用宏定义表示数据类型和用typedef定义数据说明符的区别。宏定义: 只是简单的字符串代换,在预处理阶段完成。typedef: 对类型说明符重新命名。在编译的时候处理。用来表示新命名的标示符具有类型定义说明的功能。

6、使用条件编译指令屏蔽调试bug
/*
        通过控制 MyDEBUG1 的值来控制编译
*/
#define MyDEBUG1     1
#if MyDEBUG1 == 0
                //format是格式控制,##表示可以没有参数,__VA_ARGS__表示变量
        #define Log(format,...) printf(format,## __VA_ARGS__)
#else
            #define Log(format,...)
#endif

void test(){
    Log("xxxxx");
}
int main(int argc, const char * argv[]) {
            Log("%d\n",10);
        return 0;

2 个回复

倒序浏览
一直不理解宏的概念,讨教了
回复 使用道具 举报
收藏下 ,细细研究下。确实不太理解这块内容
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马