#define宏作用

预处理器的任务

简单来讲,预处理器的任务就是执行源代码中的预处理指令,并对源代码进行相应的处理。因此,从预处理指令的类型来讲,预处理器的任务包括如下的几个部分:

将其他文件包含到当前文件中。

定义宏,用来取代某些复杂文本。

定义类似函数的宏,以更加灵活的方式控制源代码。

实施条件编译,即有选择地编译源代码的某些部分。

头文件中一般是函数、类等的声明,包含到当前文件中后,就可以在当前文件中引用头文件中的函数、类等。

宏的作用

使用预处理指令#define定义的宏主要有三个方面的作用:

替代字面常量。

替代运算符。

声明某个符号已经被定义,通常用于条件编译。

除了可以用宏替代字面常量,还可以用宏替代某些运算符,包括加、减、乘、除、逻辑与和逻辑非等,甚至函数和语句块的花括号。例如:

#define ADD     +

#define SUB     –

#define MUL     *

#define DIV     /

#define AND     &&

#define OR  ||

#define NOT     !

#define BEGIN {

#define END     }

#define OUT cout<<

利用上述宏定义,可以编写出貌似违反C++语法、但实际上合法的源代码。例如:

void Function()

BEGIN

int x = 1 ADD 2;

int y = 3 MUL 4;

if(NOT x OR Y)

BEGIN

OUT Y;

END

END

说明

除了简单地替换某些操作符,还可以定义一些类似函数的宏,即可以接受参数的宏。其定义和使用都类似于函数,但又与函数不同,详细内容请参考后面的小节。

声明已定义符号

利用预处理指令#define可以声明某个符号(宏名)已经定义过了,其格式如下:

#define SOME_NAME

如果在源代码中存在上述语句,则对预编译器来说,一个名称为SOME_NAME的宏已经被定义了,尽管没有指明要替换的文本。当然,也可以为该宏名指定要替换的文本,尽管没有必要。宏的这种特性通常应用在条件编译中。有关条件编译的内容将在后面介绍。

预定义的宏

在C++标准中,规定了一些预定义的宏。也就是说这些宏不需要由开发者定义,而是由预编译器提供,开发者只要使用即可。如表11-1所示是一些常用的预定义宏。

表11-1 常用的预定义宏

[插图]

当心

上述预定义宏两侧都是两道下画线,而不是一道。

其中宏__LINE__表示该宏所在行的行号。这个行号可以用预处理指令#line进行修改。预处理指令#line的使用格式如下:

#line新的起始行号

如果在源代码文件中存在上述预处理指令,则该指令的下一行将以新的起始行号为编号,以后各行以此为基准进行递增。譬如#line指令定义了新的起始行号为100,则在该指令的下一行使用宏__LINE__得到的值就是100。#line指令也可以修改宏__FILE__所表示的文件名,其格式如下:

#line新的起始行号 "新文件名"

下例使用预定义的宏输出某些源代码的信息,程序如示例代码11.1所示。

示例代码11.1

#include

#include

using namespace std;                       // 使用名称空间std

void fun()

{

cout<<"函数名:     "<<__func__<<endl;

}

int main(int argc, char *argv[])           // 主函数

{

cout<<"——输出预编译信息——"<<endl;

cout<<"文件名:     "<<__FILE__<<endl;

cout<<"行号:       "<<__LINE__<<endl;

cout<<"预编译日期: "<<__DATE__<<endl;

cout<<"预编译时间:  "<<__TIME__<<endl;

fun();

#line 100 "测试文件"

cout<<"——修改行号和文件名——"<<endl;

cout<<"文件名:     "<<__FILE__<<endl;

cout<<"行号:       "<<__LINE__<<endl;

system("PAUSE");                       // 暂停程序

return EXIT_SUCCESS;

}

建立一个控制台工程,并将上述代码复制到源文件中,编译并运行,结果如图11-3所示。

[插图]

图11-3 输出预编译信息结果

带参数的宏

简单的宏定义,如上节例子所示,只能进行简单的文字替换,扩展能力有限。如果宏能够像函数那样带有参数,并根据参数的不同自动展开成不同的文本,则宏的扩展能力将大大提高。实际上,在C++标准中,是可以利用预处理命令#define定义带参数的宏的。

定义带参数的宏(类似与函数格式)

定义带参数宏的语法同定义函数类似,在紧跟宏名之后有用括号包围起来的参数列表,但没有返回值类型、参数类型等的声明。其语法如下:

#define宏名(参数1, 参数2, , 参数n) 可替换文本

如果可替换文本一行写不完,可以分成多行,并在每一行的结尾处加上续行符号“\”(除了最后一行)。其语法如下:

#define宏名(参数1, 参数2, , 参数n) 可替换文本行1 \

可替换文本行2 \

可替换文本行m

当心

要定义带参数的宏,则在宏名和左括号之间不能有空格(或制表符),否则就成了普通的宏定义,括号及其里面的内容也将会成为可替换文本的一部分。但是,在括号中的各参数之间可以任意添加空格。

在可替换文本中可以引用括号中的参数,从而根据参数的不同,展开成不同的源代码文本。例如定义一个比较两数大小的宏:

#define LESS(x, y)  x < y

假设在程序中有如下的引用:

bool result = LESS(3, 4);

则经过预编译后,上述语句将展开成如下的语句:

bool result = 3 < 4;

在上例中,LESS是带参数宏的名称,x和y则是该宏的形式参数(类似函数的形参)。在引用LESS宏时,可以用实参(类似函数的实参)3和4分别替换形参x和y。当进行宏展开时,可替换文本中用到形参的地方也将由相应实参一一替代。

下例定义一个宏,接受两个参数,然后比较这两个参数的大小,并输出其中的较小值,程序如示例代码11.2所示。

示例代码11.2

#include

#include

using namespace std;                    // 使用名称空间std

// 定义宏,输出两个数中的较小值

// 注意:以双斜杠引导的注释不能写到宏定义中,否则将成为宏的一部分

// 但是可以加包围的注释,而且必须加在续行符之前

#define LESS(x, y) {  \

if( x < y ) \

{ \

cout<<"较小值:"<<x<<endl; \

} \

else \

{ \

cout<<"较小值:"<<y<<endl; \

} \

}

int main(int argc, char *argv[])

// 主函数

{

cout<<"——求较小值的宏——"<<endl;    // 输出提示信息

LESS( 1, 2 )                           // 求1和2中的较小值,注意语句结尾没有分号

LESS( 5, 4 )                           // 求5和4中的较小值,注意语句结尾没有分号

cout<<endl;

system("PAUSE");                       // 程序暂停执行

return EXIT_SUCCESS;

}

建立一个控制台工程,并将上述代码复制到源文件中,编译并运行,结果如图11-4所示。

[插图]

图11-4 用宏求较小值并输出结果

提示

在上述例子中,使用了带参数的宏LESS,但是在语句的结尾处并没有分号。乍一看好像不符合C++的语法规范,但是实际上并没有错。这是因为宏是在预编译时处理的,而不是编译期。而且,宏展开后的结果符合C++语法规范,所以这些语句的结尾处没有分号并不会出错。

特别注意:宏主要是展开,并不是那么智能,若常量等按照展开思想,如#define a(x) x+x  调用为8*a(5),本来想是8*(5+5)为80,实际是8*5+5为45

原文地址:https://www.cnblogs.com/tangjunjun/p/11676506.html

时间: 2024-10-17 06:35:12

#define宏作用的相关文章

const基础知识、const在C++和C中的异同、const与#define宏定义的异同

1.const基础知识 (1)用const定义常量 const int a = 5;   //定义了一个int型常量a,其值为5 (注:在C++中将其存储在符号表中(key,value),并不分配内存空间,只有在取地址或者定义为全局变量在其他文件中使用时才分配内存空间) (2)const与指针 1 const int* p1 = &a; //p1是指向常量a的指针,a的值不能通过指针p1改变 2 3 int* const p2 =&b; //p2是只能指向b的指针,b的值可以通过p2改变

define宏定义中的#,##,@#及\符号

define宏定义中的#,##,@#及\符号 在#define中,标准只定义了#和##两种操作.#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串. 1.# (stringizing)字符串化操作符.其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串.其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前. 如: #define example(instr) printf("the input string is:\t%s\n",#

#define 宏定义 与 typedef 类型定义

一 #define 宏定义 1. 宏基本定义 #define 宏名 宏定义字符串 # 表示它在预编译处理中起作用,而不是真正的 C 语句,行尾无须跟分号,如果加了分号,分号作为宏定义的一部分. 宏名常采用大写字母,宏名与定义字符串间用空格分隔,所以宏名之间不能有空格. 宏定义字符串是宏名对应的具体实现过程,可以是任意字符串,中间可以有空格,以回车符作为结束. 栗子:#define PI 3.1415926 宏的用途: 1)符号常量,如PI.数组大小定义,以增加程序的灵活性 2)简单地函数功能实现

iOS 7:漫谈#define 宏定义(转)

iOS 7:漫谈#define 宏定义 #define宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多.但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加. 如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身可能并不漂亮优雅XD).但是因为宏定义对于很多人来

iOS 7:漫谈#define 宏定义

#define宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多.但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加. 如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身可能并不漂亮优雅XD).但是因为宏定义对于很多人来说,并不像业务逻辑那样是每天会接触的东西

typedef与define宏定义用于声明新的类型之间的区别

摘自<c专家编程> typedef可以看成一种彻底的封装类型,在typedef声明类型之后不能再往里面增加其他的内容. 例子: #define peach int unsigned peach i; //没问题 typedef int banana; unsigned banana i; //错误,不能增加unsigned #define宏定义只是用于简单的替换 #define int_ptr int * int_ptr chalk, cheese; int * chalk, cheese;

程序猿之---C语言细节28(const变量初始化、数组大小用const变量细节、const变量与#define宏、volatile修饰)

主要内容:const变量初始化.数组大小用const变量细节.const变量与#define宏.volatile修饰 一.const变量初始化时必须赋值 二.const变量在C++中可以做数组大小元素.在C中不行,因为它是变量 三.const和#define区别:内存分配 四.volatile修饰一些变量:易被操纵系统.硬件.多线程修改的变量 #include <stdio.h> int main() { /* 测试1 */ const int b; // 不初始化会报错 // b = 2;

#define宏,const关键字 C++

一.#define宏定义 1.宏定义,像这样的就是宏定义:#define PI 3.14159: 2.宏定义格式:#define 宏名称 宏值:宏名称就是要定义的宏,通常用一个大写的有意义的名称来表示:宏值就是这个宏所代表的常量.: 3.#define是预编译指令: 4.宏的本质是一种替代. 5.当预编译程序在处理源代码时,如果发现代码中使用了宏,就会用宏的值来代替宏. 6.使用宏的好处:使用宏给常量一个名分,除了可以避免多次输入重复使用的: 7.例子: 宏让代码更简洁明了 #define MI

iOS define 宏定义 和 const定义常量区别

const   const 是c++中的修饰符.  c++中常用来定义常量,修饰左值. #define 宏定义语句, 在预处理阶段直接做文本替换,不做类型检查. 它们之间的最大区别: 1.  对于const 变量,系统只给了一个相应的内存地址,而#define则是给出了一个立即数.因为const变量是存放在内存的静态区域中,所以在程序运行过程中const变量只有一个拷贝,而#define 所定义的宏变量却有多个拷贝,所以宏在程序运行过程中所消耗的内存要比const变量的大得多.#define所定