`

【2011.8.2】<C++学习笔记>预处理功能

    博客分类:
  • C++
c++ 
阅读更多
预处理功能介绍
       为有助于执行编译过程,经常可以使用一些预处理命令。每条预处理命令都具备一定的预处理功能。       常用的预处理命令有以下三项:
              1.宏定义命令
              2.文件包含命令
              3.条件编译命令。
预处理命令具有以下特点:
1.在左边加 # 号,作为标志。
2.一般独占一行。
3.预处理命令不是编程语句,因此句末不加分号。
4.在正常编译过程之前作为预备动作而执行,编译过程结束后不占用存储空间。


宏定义命令
简单宏定义
例如:
#define  PI  3.14159
#define  SIZE  80
宏定义命令被执行时,用字符串替代宏名,例如用3.14159替代PI,用80替代SIZE,等。
[例1]计算圆周长和面积。
#define  PI  3.14159
void main( )
{
        double circum, area, r = 3;
        circum = 2 * PI * r;
        area = PI * r * r;
}
宏定义命令被执行时,不作语法检查。例如,用户希望将EXEC宏替代整句语句(例如int i=5;),使用以下宏:
#define  EXEC  int i=5
其中遗漏了分号(int i=5;才是完整语句),但因不作语法检查,因此查不出以上错误,而直到编译系统将其它使用该宏的语句进行编译时才能发现错误。
带参数宏定义
注意:带参数宏定义并不是函数
例如:
#define  ADD(x,y)  x+y
[例1]计算两数之和。
#include <iostream.h>
#define  ADD(x,y)  x+y
void main( )
{
        int a(40), b(50);                        //将a、b分别初始化为40、50
        int sum = ADD(a, b);        //宏替代结果为int sum = a + b;
        cout<<sum;
}
运行结果:
90

宏替代的操作服从于运算符的优先级,见下例:
[例2]计算数的平方。
// macro_3.cpp
// Attention in defining macro
// From Lv's book, p.85
#define         SQ(x)  x*x
#include <iostream.h>
void main()
{
        int a = 2, b = 3;
        cout << SQ(a+b) << endl;
        //由于乘法运算符优先级高于加法运算符,所以执行a+b*a+b
}
/* Result:
        should be 25, but we get
        a+b*a+b=11                */       
问题出在优先级,应改正如下:
// macro_1.cpp
#define         SQ(x)                 (x)*(x)
#include <iostream.h>
void main()
{
        int a = 2, b = 3;
        cout << SQ(a+b) << endl;        //即(a+b)*(a+b)
}
/* Result:
        25                        */
请注意:宏不是函数(子程序)!
宏与函数的区别:宏节省时间但占用空间;函数节省空间但增加时间!

文件包含
如果以上所述的宏定义语句很多,则可将它们包含于一个单独的文件中,例如 "macros.h" 中。此macros.h文件内容例如可为:
// macros.h
#define MAX 32 #define sq(n)         (n)*(n)
#define  PI  3.14159
…        …
此时用户程序可简化为只包含以下一条语句:
#include         "macros.h"
即可执行以上所有宏命令。
以上macros.h称为头文件(header files)(或称包含文件,include files)。
其中系统所定义的头文件名称(例如iostream.h)使用尖括弧< >将头文件名称iostream.h包括起来,系统就根据这点到系统的文件夹中去调用;而用户自定义的头文件则用双引号" "将头文件名称包括起来,例如"macros.h"。系统就根据这点到用户程序的文件夹中去调用。请注意区别此点。
C++语言系统中有很多头文件,它们除包含宏替代定义语句外,更主要包含函数原型和类的定义或类的接口,及其所用各种数据类型的全局变量、外部静态变量和常量的定义。


条件编译
条件编译命令的功能是规定某些语句(或某个程序块)在一定条件下才参加编译,否则跳过不予理睬。
其主要用途为:防止遗漏定义或避免重复定义;以及在测试时增加某些测试语句,以实现调试跟踪的目的。本节主要讲防止遗漏定义或避免重复定义的功能。
其格式为:
#ifdef        (常量表达式)(或 #if defined(常量表达式))
                [条件编译语句]
#endif

#ifndef        (常量表达式)(或 #if not defined(常量表达式))
                [条件编译语句]
#endif
以上语句中,当常量表达式无定义时,就编译两个条件编译命令#ifdef(或#ifndef)与#endif之间的条件编译语句。
条件编译命令也可表达如:
#if        (常量表达式)
                [条件编译语句]
#endif
此时如常量表达式非零,则满足编译条件,编译两个条件编译命令#if与#endif之间的条件编译语句。
现在讲解其避免遗漏定义和避免重复定义的功能:
以下使用        #ifndef  MAX,此即(# if not defined MAX)或(#if  !defined  MAX) 
例题:
// test_ifndef_1.cpp
// To prevent the missing of macro definition
#include <iostream.h>
#ifndef MAX
#define MAX 32
#endif
void main()
{
        cout << "MAX is " << MAX << endl;
}
/* Result:
    MAX is 32                                */
上例中MAX没有定义,所以执行条件编译语句#define MAX 32语句。
例此例中MAX已经定义过了,故不执行条件编译语句
// test_ifndef_2.cpp
// To prevent the missing of macro definition
#include <iostream.h>
#define MAX 10
#ifndef MAX
#define MAX 32
#endif
void main()
{
        cout << "MAX  is " << MAX << endl;
}
/* Result:
    MAX  is  10                                */
上例中MAX已被定义为等于10,所以不执行条件编译语句#define MAX 32语句。再说,如果真是执行了条件编译语句#define MAX 32语句,必将会出现如下警告:
warning: 'MAX' : macro redefinition
test_ifndef_2.cpp(6) : see previous definition of 'MAX'
再看避免重复包含头文件的例子:
[例3]防止重复包含头文件。
设已有头文件如下:
// ifndef.h
// To avoid the duplication of include files
#if        !defined(_IFNDEF_H)
#define _IFNDEF_H
int var=1;                //global variable
#endif                //_IFNDEF_H
用户应用程序如下:
// test_ifndef_3.cpp
// To prevent the duplication of macro definition
#include <iostream.h>
#include "ifndef.h"
#include "ifndef.h"                //看似重复包含,实则不予执行
void main()
{
        cout << "变量var = " << var << endl;
}
/* Result:
变量var = 1
*/
此程序中虽然多了一句#include "ifndef.h",但第二句不起作用。原因在于头文件中使用了条件编译功能。怎么知道重复包含的第二句不起作用?因为如果包含第二句的话,将会出错。如下:
// test_ifndef_4.cpp
// The error of the duplication of macro definition
#include <iostream.h>
int var=1;
int var=1;
void main()
{
        cout << "变量var = " << var << endl;
}
/* Result : Not working
error C2374: 'var' : redefinition; multiple initialization
*/
在任何头文件中,都必须使用上述条件编译语句以便避免重复包含。在有些头文件中,也可能使用语句#pragma   once,只要在头文件的初始部分加入这条指令,就能够保证头文件只被编译一次。有时同时使用条件编译语句#if  !defined(_IFNDEF_H)和#pragma语句。
=========================================

转载时请表明出处:http://www.cofftech.com/thread-5771-1-1.html
=========================================
0
1
分享到:
评论

相关推荐

    DevcppConsolePauser.exe

    DevC++的ConsolePauser.exe。 程序运行后起暂停功能。 适用Windows7 方法:ConsolePauser.exe (filename) (parameters)

    dmg转iso工具 dmg2iso

    dmg转iso工具 dmg2iso dmg2iso v0.2c by vu1tur (vu1tur@gmx.de) Syntax: dmg2iso &lt;filename.dmg&gt; &lt;filename.iso&gt;

    css 导航菜单(标签页)设计

    Enjoy ...&lt;br&gt;&lt;br&gt;html代码部分为&lt;br&gt;&lt;br&gt;&lt;div id="tabsB"&gt;&lt;br&gt;&lt;ul&gt;&lt;br&gt;&lt;li&gt;&lt;a href="#" title="Link 1"&gt;&lt;span&gt;Link 1&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;br&gt;&lt;li&gt;&lt;a href="#" title="Link 2"&gt;&lt;span&gt;Link 2&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;br&gt;...&lt;br&gt;...

    GPIO模拟I2C程序实现

    #include &lt;linux/module.h&gt; #include &lt;linux/config.h&gt; #include &lt;linux/errno.h&gt; #include &lt;linux/miscdevice.h&gt; #include &lt;linux/fcntl.h&gt; #include &lt;linux/init.h&gt; #include &lt;linux/delay.h&gt; #include &lt;linux/...

    用c++編的电话簿,希望對你有用

    cout &lt;&lt; "请按回车键继续......\n"; cin.get(pause); system("cls"); //执行系统命令:cls-清屏 int choice; list.load_list_from_file(); // 从文件中加载数据 do { // 主菜单显示 cout &lt;&lt; "1 - ...

    c++头文件大全.txt

    2. `&lt;array&gt;`:提供了固定大小数组的封装,简化了数组的操作。 3. `&lt;bitset&gt;`:提供了一个可以动态操作的位集容器,可以用来存储一组二进制位。 4. `&lt;chrono&gt;`:用于处理时间和日期,支持时间点、时间间隔等类型。...

    C语言标准函数库详解.pdf

    这些头文件包括:&lt;assert.h&gt;、&lt;ctype.h&gt;、&lt;errno.h&gt;、&lt;limits.h&gt;、&lt;locale.h&gt;、&lt;math.h&gt;、&lt;setjmp.h&gt;、&lt;signal.h&gt;、&lt;stdarg.h&gt;、&lt;stddef.h&gt;、&lt;stdio.h&gt;、&lt;stdlib.h&gt;、&lt;time.h&gt;等。 每个头文件都提供了不同的函数,...

    JPEG解码源程序(C++)

    色彩模型&lt;br&gt; 2. DCT (离散余弦变换)&lt;br&gt; 3. 重排列 DCT 结果&lt;br&gt; 4. 量化&lt;br&gt; 5. 0 RLE 编码&lt;br&gt; 6. 范式 Huffman 编码&lt;br&gt; 7. DC 的编码&lt;br&gt;解码过程简述&lt;br&gt; 8. 一个数据单元 Y 的解码&lt;br&gt; 9. JPG 文件(Byte 级)...

    JSP图书管理系统

    &lt;td width="8" height="24"&gt;&nbsp;&lt;/td&gt; &lt;td width="200"&gt;&nbsp;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td height="99"&gt;&nbsp;&lt;/td&gt; &lt;td&gt;&lt;%@ include file="denglu.jsp"%&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/table&gt; &lt;table width="208" border="0...

    c++学习笔记.pdf

    8. C++的编译过程一般包括预处理、编译及优化、汇编和链接几个阶段。预处理阶段负责处理源代码中的预处理指令,如宏定义和文件包含。编译及优化阶段负责将预处理后的代码转换成汇编代码,并进行优化。汇编阶段将汇编...

    c语言设计Brian W. Kernighan Dennis M. Ritchie

    B.2 字符类测试:&lt;ctype.h&gt; B.3 字符串函数:&lt;string.h&gt; B.4 数学函数:&lt;math.h&gt; B.5 实用函数:&lt;stdlib.h&gt; B.6 诊断:&lt;assert.h&gt; B.7 变量变元表:&lt;stdarg.h&gt; B.8 非局部跳转:&lt;setjmp.h&gt; B.9 信号处理:...

    c++和c的头文件大全

    4. `&lt;deque&gt;`、`&lt;list&gt;`、`&lt;map&gt;`、`&lt;set&gt;`、`&lt;queue&gt;`、`&lt;stack&gt;` 和 `&lt;vector&gt;`:这些是STL(Standard Template Library)容器,分别表示双端队列、线性列表、映射、集合、队列、堆栈和动态数组。 5. `&lt;exception...

    Visual C++ 编程资源大全(源码 系统)

    1,cccode.zip&lt;br&gt;一个监控别人计算机的程序(65KB)&lt;END&gt;&lt;br&gt;2,cihcn.zip&lt;br&gt;CIH病毒1.4版本之中文注释(25KB)&lt;END&gt;&lt;br&gt;3,regmonsrc.zip&lt;br&gt;监控win9x下文件的读写(251KB)&lt;END&gt;&lt;br&gt;4,quickprt.zip&lt;br&gt;增强的quickrpt(70...

    Visual C++ 编程资源大全(控件 网络)

    ddialw.EXE &lt;br&gt;DameWare公司出品的电话拨号控件(170KB)&lt;END&gt;&lt;br&gt;6,dipw.EXE &lt;br&gt;DameWare 公司出品 IP 地址控件(169KB)&lt;END&gt;&lt;br&gt;7,dm10e.ZIP &lt;br&gt;发送 E.Mail 的控件(117KB)&lt;END&gt;&lt;br&gt;8,dsdns_eval.EXE &lt;br&gt;IP地址...

    网站自动模拟器(AutoWeb)(c#源码)

    &lt;br&gt; 3.EntryDataByID(参数1,参数2)&lt;br&gt; 功能:模拟输入文本到文本框&lt;br&gt; 参数1:为网页源代码中的输入框(文本框)ID属性&lt;br&gt; 参数2:要输入的文本&lt;br&gt; 实例:EntryDataByID(username,admin);&lt;br&gt; 4.EntryDataByName...

    zip.h zip库要用到

    zip.h zip库要用到zip.h zip库要用到zip.h zip库要用到zip.h zip库要用到

    stdafx.h的作用

    `stdafx.h`中包含了项目所需的所有基础头文件,例如`&lt;afxwin.h&gt;`、`&lt;afxext.h&gt;`、`&lt;afxole.h&gt;`、`&lt;afxodlgs.h&gt;`等,这些都是MFC的核心和扩展组件,以及OLE、对话框和自动化类的相关头文件。根据项目类型和用户在...

    C++学习笔记.chm

    《C++学习笔记》是一部非常实用的资源,适合那些对C++编程语言有着浓厚兴趣或者正在学习C++的初学者。这份笔记详细介绍了C++语言的基础知识、核心概念以及高级特性,旨在帮助读者掌握C++编程的核心技能。 C++是...

    Java秒杀系统方案优化高性能高并发学习实战源代码以及笔记..zip

    Java秒杀系统方案优化高性能高并发学习实战源代码以及笔记..zip 章节笔记 第1章-课程介绍及项目框架搭建 知识点 使用spring boot 搭建项目基础框架 使用Thymeleaf做页面展示,封装Result统一结果 集成 mybatis + ...

    struts2+kindEditor4.1.7

    &lt;param-value&gt;UTF-8&lt;/param-value&gt; &lt;/init-param&gt; &lt;init-param&gt; &lt;param-name&gt;forceEncoding&lt;/param-name&gt; &lt;param-value&gt;true&lt;/param-value&gt; &lt;/init-param&gt; &lt;/filter&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;Set ...

Global site tag (gtag.js) - Google Analytics