预处理功能介绍
为有助于执行编译过程,经常可以使用一些预处理命令。每条预处理命令都具备一定的预处理功能。 常用的预处理命令有以下三项:
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
=========================================
为有助于执行编译过程,经常可以使用一些预处理命令。每条预处理命令都具备一定的预处理功能。 常用的预处理命令有以下三项:
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
=========================================
发表评论
-
C++主流预处理,编译和链接过程
2011-09-11 13:26 10591在C++的程序的编写过程 ... -
c++ 一个简单的链表
2011-09-11 13:13 99571 #include <stdio.h> 2 # ... -
C++经典电子资料下载合集
2011-07-11 11:43 36561.C++ 逆向工程 pdf高清下 ... -
《C++学习笔记》静态数据成员
2011-05-20 13:15 1122=============================== ... -
《C++学习笔记》不同数据类型对象的构造函数和析构函数的调用顺序
2011-05-19 01:34 1349=============================== ... -
《C++学习笔记》子对象构造函数和析构函数的调用顺序
2011-05-19 01:34 1513=============================== ... -
《C++学习笔记》子对象的初始化
2011-05-19 01:33 1731=============================== ... -
《C++学习笔记》特定类型数据成员的初始化
2011-05-17 10:56 1293========== ... -
《C++学习笔记》析构函数(destructor)
2011-05-17 10:55 1145=============================== ... -
《C++学习笔记》对象间非静态数据成员的复制
2011-05-16 12:04 1010=============================== ... -
《C++学习笔记》带缺省参数的构造函数(constructor with default arguments)
2011-05-16 12:03 2698=============================== ... -
《C++学习笔记》构造函数及特点
2011-05-16 12:02 1305========== ... -
《C++学习笔记》【封装性】类的接口部分与实现部分的分离
2011-05-16 11:41 1633========== ... -
《C++学习笔记》【封装性】对象及其内存存储内容
2011-05-16 11:40 842========== ... -
《C++学习笔记》【封装性】成员函数的说明和定义
2011-05-16 11:37 950成员函数可在类体之内、也可在类体之外被定义。规范的做法是将成员 ... -
《C++学习笔记》【封装】封装性
2011-05-16 11:35 713以下程序依靠封装,能 ...
相关推荐
1. **更改头文件名称**:将 `#include <iostream.h>` 改为 `#include <iostream>`,这样可以直接访问到 C++ 标准库中的 I/O 相关功能。同时,需要添加 `using namespace std;` 来使用 `std` 命名空间中的函数。 ``...
cout << "请按回车键继续......\n"; cin.get(pause); system("cls"); //执行系统命令:cls-清屏 int choice; list.load_list_from_file(); // 从文件中加载数据 do { // 主菜单显示 cout << "1 - ...
[目录]Java学习笔记(推荐) <br> 6. [目录]JDBC文档 <br> 7. [目录]RMI 文档 <br> 2. [目录]Java资源(文档-书籍-下载-注册码) <br> 1. [目录]License 和注册码 <br> 2. [目录]好书推荐 <br> 3. [目录]关于Java的...
这些头文件包括:<assert.h>、<ctype.h>、<errno.h>、<limits.h>、<locale.h>、<math.h>、<setjmp.h>、<signal.h>、<stdarg.h>、<stddef.h>、<stdio.h>、<stdlib.h>、<time.h>等。 每个头文件都提供了不同的函数,...
<td width="8" height="24"> </td> <td width="200"> </td> </tr> <tr> <td height="99"> </td> <td><%@ include file="denglu.jsp"%></td> </tr> </table> <table width="208" border="0...
button 4 up<br> 0100h = button 5 down<br> 0200h = button 5 up<br> 0400h = mouse wheel<br>6 2 Mouse wheel data<br>8 4 Not used<br>12 4 X position<br>16 4 Y position<br>20 4 Device specific ...
4. `<deque>`、`<list>`、`<map>`、`<set>`、`<queue>`、`<stack>` 和 `<vector>`:这些是STL(Standard Template Library)容器,分别表示双端队列、线性列表、映射、集合、队列、堆栈和动态数组。 5. `<exception...
1,cccode.zip<br>一个监控别人计算机的程序(65KB)<END><br>2,cihcn.zip<br>CIH病毒1.4版本之中文注释(25KB)<END><br>3,regmonsrc.zip<br>监控win9x下文件的读写(251KB)<END><br>4,quickprt.zip<br>增强的quickrpt(70...
【C++ 学习笔记】深入理解编程与C++基础 C++是一种强大的、面向对象的编程语言,广泛应用于系统软件、游戏开发、嵌入式系统以及许多高性能应用。学习C++不仅仅是掌握语法,更重要的是理解编程的核心概念,以便更好...
根据给定的信息,我们可以将这份代码以及描述的内容总结为以下相关的C++知识点: ### C++基础知识 1. **头文件的包含**: - `#include "iostream"`:...对于学习C++编程的学生而言,这是一份非常有价值的实践案例。
<br>C++的沉迷与爱恋 .txt<br>Curses编程简介.txt<br>Kingofark关于学习C++的50个观点 .txt<br>kingofark详解他的50个观点(上) .txt<br>kingofark详解他的50个观点(下) .txt<br>kingofark详解他的50个观点(中).txt...
<groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.x.y.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>...
- <stdlib.h>:实用功能,如动态内存管理和随机数生成。 - <string.h>:字符串处理。 - <tgmath.h>:类型通用数学宏。 - <wctype.h>:宽字符分类和转换。 以上是根据文件内容,整理的C语言及C++标准库中常用头文件...
#include <stdio.h> #include <stdlib.h> int main(void) { printf("Calling abort()\n"); abort(); return 0; /* 这行代码永远不会被执行 */ } ``` ### 2. `abs` 函数 - **功能**:计算整数的绝对值。 ...
struts-1.3.8 包(<br><br>antlr-2.7.2.jar<br>bsf-2.3.0.jar<br>commons-beanutils-1.7.0.jar<br>commons-chain-1.1.jar<br>commons-digester-1.8.jar<br>commons-fileupload-1.1.1.jar<br>commons-io-1.1.jar<br>...
<br> 3.EntryDataByID(参数1,参数2)<br> 功能:模拟输入文本到文本框<br> 参数1:为网页源代码中的输入框(文本框)ID属性<br> 参数2:要输入的文本<br> 实例:EntryDataByID(username,admin);<br> 4.EntryDataByName...
通讯录管理程序源代码<br/>人事管理系统<br/>仓库管理系统<br/>打字源程序<br/>俄罗斯方块源代码<br/>遍历文件夹并建成目录树<br/>个人考勤软件开发<br/>进销存软件 beta.rar<br/>学生成绩管理系统(VC++).rar<br/>...
zip.h zip库要用到zip.h zip库要用到zip.h zip库要用到zip.h zip库要用到
《C++学习笔记》是一部非常实用的资源,适合那些对C++编程语言有着浓厚兴趣或者正在学习C++的初学者。这份笔记详细介绍了C++语言的基础知识、核心概念以及高级特性,旨在帮助读者掌握C++编程的核心技能。 C++是...
25 <param-value>UTF-8</param-value> 26 </init-param> 27 </filter> 28 29 <filter-mapping> 30 <filter-name>encodingFilter</filter-name> 31 <url-pattern>*.do</url-pattern> 32 </filter-mapping> 33 34 ...