C / C++ 编译预处理

今天做练习用到头文件包含时遇到了 redefinition 的报错。仔细一看才发现是 我没有很好地使用条件编译来协调头文件包含关系(平常说的 “头文件卫士”就这么回事 )。
于是找来尘封已久的<<C++程序设计语言>>,复习了编译预处理这一章节。做点笔记如下:

C预处理程序 :
           在用C编译程序对C源代码进行编译之前,即在语法分析、代码生成和优化之前,由C 预处理程序对源代码进行第一次处理。处理时,它忽略注释语句,加入.h头文件,并按定义进行替换。预处理的输出,即是编译程序的输入。
预处理命令必须单行书写,不以 " : " 结束。
编译预处理包括: 宏定义;条件编译;  文件包含。

一、 宏定义

宏 : C语言源程序中用一个标识符(宏名)来表示一个字符串。
1、宏名惯用全大写字母命名。仅作简单置换,不分配内存空间。
2、宏替换只对单独的宏名单词进行,对于括在引号中的字符串不起作用。
3、宏定义允许嵌套。
4、带参数的宏展开时,是用实参字符串替换形参字符串,由于运算符的优先级问题,可能发生的逻辑错误。比较好的办法是宏定义的形参加括号。

#define MULTIPLY(m, n)   (m)*(n)
int a = 5,  b = 6;
cout<<MULTIPLY(a+b, a-b);     // 输出为 :-11.
// 如果 宏定义是对参数不加括号,直接写 m*n, 则结果为 29, ( 5+6×5-6 );
5、宏名与参数表间不能有空格,否则将作为无参数宏来处理。
6、宏定义中,若替换字符串中的形式参数在引号中,则宏展开时不被实参替换。但如果在替换字符串中,形式参数以#作为前缀,那么宏展开时它将被带引号的实参字符串替换.

#define MYPRINT1(exp) printf("exp=%d/n",exp)
#define MYPRINT2(exp) printf(#exp"=%d/n",exp)
void main()
{ MYPRINT1(2+3);     /*宏展开 print("exp=%d/n",2+3); */         exp=5
  MYPRINT2(2+3);     /*宏展开 print("2+3" "=%d/n",2+3); */     2+3=5
  /*其中字符串被连接起来,即print("2+3=%d/n",2+3); */
}
7、深刻体会带参宏定义和函数中参数的区别。(执行时间是预处理还是编译;传递还是直接替换;是否占据内存空间等方面 )。
8、取消宏: #undef 标识符(在取消一个宏之前,那个宏一直有效,如果在取消之前定义了一个同名的宏,则新定义的宏覆盖原先的宏)。

二、条件编译

对源程序的一部分内容进行编译,即不同的编译条件产生不同的目标代码。使源代码能更迅速、更容易地进行修改,并使目标代码缩短。这样,当程序在不同系统上编译、在同一系统不同编译器上编译或进行不同目的的编译时,减少对程序语句的修改。
重要作用: 直接取舍程序语句和协调多个头文件。
常见的三种格式:
1、
#ifdef 标识符
       程序段1 
 #else
       程序段2
#endif  // 把 #ifdefine 换为 #ifndefine 为另一种。
2、
 // 表达式为常量整型表达式(其中不能包含sizeof、强制类型转换运算符或枚举常量),非 0 即为真。
# if  表达式1
       程序段1
       …
# elif  表达式m
       程序段m
# else
       程序段n
#endif

三、文件包含

文件包含命令 #include 把“文件名”指定的文件内容复制到本文件(即是用指定文件的内容去替换# include命令行). 被包含文件中一般定义符号常量、宏,或声明函数原型,类和类型定义。 一般不在被包含文件中定义变量。
让我们看一个我今天遇到的一个类似问题的正确做法:(避免重复定义)

zp.h 文件:
#ifndef ZP
#define ZP
int a = 5;
#endif

zp1.h 文件:
#include "zp.h"
int b= a+1;

zp2.h 文件:
#include "zp.h"
int c = a+2;

main.cpp 文件
#include "zp1.h":
#include "zp2.h"
void main() {
   cout<<a<<endl<<b<<endl<<c<<endl;     // 输出 5、6、7
} 若不在zp.h 中用条件编译,则会报错  'a' : redefinition; multiple initialization”

学而时习之,不亦乐乎。 --- Confucius.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值