科锐课堂笔记:2017/3/13 宏与预处理指令

来源:互联网 发布:lol英雄详细数据 编辑:程序博客网 时间:2024/04/24 17:03

  基本功只能花时间自己练,别人代劳不得。


  全局变量必须导出符号,静态全局是文件作用域(私有)所以不导出符号,注在汇编中全局变量不修饰默认指static静态全局(显示声明public才会导出符号)。静态局部由于使用名称粉碎机制就算导出符号别的函数也用不了(检查名字不匹配)。extern “C”声明使用C风格的名称粉碎。


  使用宏相当于编译器帮你自动化完成查找替换的功能,而且宏更具有灵活性,一则可以定义带参数的宏,二来宏是不会替换字符串里的内容的。(引号内)


  宏定义格式:
  无参宏:#define 宏名 内容(可空)
  宏名一般名称全大写,以区分函数。当内容为空此时定义了一个说明宏,说明宏可用来当注释信息看或配合预处理指令改变程序内容流程。
  有参宏:#define 宏名(参1,参2,…) 表达式
  比如定义一个取两者最大值的MAX宏,#define MAX(a,b) (((a)>(b)) ? (a):(b))。使用有参宏需要注意的是,因为宏最终都会展开替换到源码中,所以在表达式内引用的参数必须要用括号括起来,不但参数,连整个表达式,当中局部的表达式都要使用括号,不用括号的话遇到运算符优先级会破坏执行流程,得不到预想中的结果。
  两个#号连接宏,末尾加\续行。编译选项</D “宏名”>表示预编译宏,在所有源文件的任何部分都能访问到。


  使用宏解决VC6 for内变量作用域BUG的例子:
  C++规定for内定义的变量属于块作用域,而在VC6中属于函数作用域,在同一个函数里使用两次for(int i=……)会报重定义错误,这里可以定义一个宏解决该问题,请看下面:
  #define for if(1)for
  或
  #define for if(0){}else for
  是不是问题已经完美解决了,这里使用宏统一了for的作用域(限制在if块内),这样无论VC6还是高版本都可以无差异编译通过了。再补充几点,后一种宏定义的想法是基于, if(0)是个不可达分支可去掉优化,if(1)是必达分支作者怕编译器作者优化水平不行,多出几行判断代码。其实微软VC系列作者水平都很高,无论必达或不可达分支都不会产生实际的代码(/O2编译选项)。


  使用宏实现模板函数的例子:
  #define DEFINE_SUM(type) type sum_##type(type a,type b) { \
      return a+b; \
  }
  #define CALL_SUM(type,a,b) sum_##type(a,b)

  在文件头部定义几个类型,如:
  DEFINE_SUM(int)
  DEFINE_SUM(float)
  然后使用CALL_SUM(int,3,5)调用int版,CALL_SUM(float,6.1,7.2)调用float版。C++的模板函数就来源于此。


  预处理指令(编译前处理):
  #号开头的关键字都是预处理指令,/P编译选项可查看.i文件,里面已经是宏展开和预处理处理后的内容。
  几个预编译指令:
  #if #else #endif
  #ifdef #else #endif
  #ifndef #else #endif
  #undef取消定义
  #pragma once只编译一次(多用于头文件)

0 0
原创粉丝点击