宏定义详解

宏定义详解

宏定义详解

2011年07月14日

宏定义有无参数宏定义和带参数宏定义两种。

无参数的宏定义的一般形式为

#标识符字符序列

其中#之后的标识符称为宏定义名(简称宏名),要求宏名与字

符序列之间用空格符分隔。这种宏定义要求编译预处理程序将源程序中随后所

有的定名的出现(注释与字符串常量中的除外)均用字符序列替换之。前面经常

使用的定义符号常量是宏定义的最简单应用。如有:

#

#

则在定义它们的源程序文件中,凡定义之后出现的单词TRUE将用1替

代之;出现单词FALSE将用0替代之。

在宏定义的#之前可以有若干个空格、制表符,但不允许有其它字符。

宏定义在源程序中单独另起一行,换行符是宏定义的结束标志。如果一个宏定

义太长,一行不够时,可采用续行的方法。续行是在键人回车符之前先键入符

号”/”。注意回车要紧接在符号”/”之后,中间不能插入其它符号。

宏定义的有效范围称为宏定义名的辖域,辖域从宏定义的定义结束处

开始到其所在的源程序文件末尾。宏定义名的辖域不受分程序结构的影响。可

以用预处理命令#undef终止宏定义名的辖域。

在新的宏定义中,可以使用前面已定义的宏名。例如,

#.5

#.

#*PI*R

#*R*R

程序中的被展开为2*3.*2.5宏定义详解,Area被展开为

3.*2.5*2.5。

如有必要,宏名可被重复定义。被重复定义后,宏名原先的意义被新

意义所代替。

通常,无参数的宏定义多用于定义常量。程序中统一用宏名表示常量

值java宏定义,便于程序前后统一,不易出错,也便于修改,能提高程序的可读性和可移

植性。特别是给数组元素个数一个宏定义,并用宏名定义数组元素个数能部分

弥补数组元素个数固定的不足。

注意:预处理程序在处理宏定义时,只作字符序列的替换工作java宏定义,不作

任何语法的检查。如果宏定义不当,错误要到预处理之后的编译阶段才能发现。

宏定义以换行结束,不需要分号等符号作分隔符。如有以下定定义:

#.;

原希望用PI求圆的周长的语句

c=2*PI*r;

经宏展开后,变成

c=2*3.*r;

这就不能达到希望的要求。

带参数宏定义进一步扩充了无参数宏定义的能力,在字符序列替换同

时还能进行参数替换。带参数定定义的一般形式为

#标识符(参数表)字符序列

其中参数表中的参数之间用逗号分隔,字符序列中应包含参数表中的

参数。在定义带参数的宏时,宏名标识符与左圆括号之间不允许有空白符,应

紧接在一起,否则变成了无参数的宏定义。如有宏定义:

#(A,B)((A)>(B)?(A):(B))

则代码y=MAX(p+q,u+v)将被替换成y=((p+q)>(u+v)?(p+

q):(u+v)。

程序中的宏调用是这样被替换展开的,分别用宏调用中的实在参数字

符序列(如p+q和u+V)替换宏定义字符序列中对应所有出现的形式参数(如

用p+q替代所有形式参数A,用u+V替代所有形式参数B),而宏定义字符序

列中的不是形式参数的其它字符则保留。这样形成的字符序列,即为宏调用的

展开替换结果。宏调用提供的实在参数个数必须与宏定义中的形式参数个数相

同。

注意:宏调用与函数调用的区别。函数调用在程序运行时实行,而宏

展开是在编译的预处理阶段进行;函数调用占用程序运行时间,宏调用只占编

译时间;函数调用对实参有类型要求,而宏调用实在参数与宏定义形式参数之

间没有类型的概念,只有字符序列的对应关系。函数调用可返回一个值,宏调

用获得希望的C代码。另外,函数调用时,实参表达式分别独立求值在前,执

行函数体在后。宏调用是实在参数字符序列替换形式参数。替换后,实在参数

字符序列就与相邻的字符自然连接,实在参数的独立性就不一定依旧存在。如

下面的宏定义:

#(x)x*x

希望实现表达式的平方计算。对于宏调用

P=SQR(y)

java宏定义

能得到希望的宏展开p=y*y。但对于宏调用q=SQR(u+v)得到的宏

展开是q=u+V*u+V。显然,后者的展开结果不是程序设计者所希望的。为能

保持实在参数替换后的独立性宏定义详解,应在宏定义中给形式参数加上括号。进一步,

为了保证宏调用的独立性,作为算式的宏定义也应加括

号。如SQR宏定义改写成:

#((x)*(x))

才是正确的宏定义。

对于简短的表达式计算函数,或为了提高程序的执行效率、避免函数

调用时的分配存储单元、保留现场、参数值传递、释放存储单元等工作。可将

函数定义改写成宏定义。所以合理使用宏定义,可以使程序更简洁。

使用一些宏跟踪调试

ANSI标准说明了五个预定义的宏名。它们是:

(两个下划线)java宏定义,对应%d

对应%s

对应%s

对应%s

如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。

记住编译程序

也许还提供其它预定义的宏名。

及宏指令在有关#line的部分中已讨论,

这里讨论其余的宏名。

宏指令含有形式为月/日/年的串,表示源文件被翻译到代码

时的日期。

源代码翻译到目标代码的时间作为串包含在中。串形式为

时:分:秒。

如果实现是标准的,则宏含有十进制常量1。如果它含有

任何其它数,则实现是

非标准的。

可以定义宏,例如:

当定义了,输出数据信息和所在文件所在行

#

#(msg,date)

(msg);(“%d%d%s”,date,,)

#else

# (msg,date)

#endif

20,宏定义防止使用是错误

用小括号包含。

例如:# ADD(a,b) (a+b)

用do{}while(0)语句包含多语句防止错误

例如:#difne DO(a,b) a+b;/

a++;

应用时:if(„.)

DO(a,b); //产生错误

else

解决方法: #difne DO(a,b) do{a+b;/

a++;}while(0)

宏中”#”和”##”的用法

一、一般用法

我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起

(这里说的是在预处理是对源文件的操作).

用法:

#

#

using std;

# STR(s) #s

# CONS(a,b) int(a##e##b)

int main()

(STR(vck)); // 输出字符串”vck”

(“%d/n”, CONS(2,3)); // 2e3 输出:2000

0;

二、当宏参数是另一个宏的时候

需要注意的是凡宏定义里有用”#”或”##”的地方宏参数是不会再展

开.

1, 非”#”和”##”的情况

# TOW (2)

# MUL(a,b) (a*b)

(“%d*%d=%d/n”, TOW, TOW, MUL(TOW,TOW));

这行的宏会被展开为:

(“%d*%d=%d/n”, (2), (2), ((2)*(2)));

java宏定义

MUL 里的参数TOW 会被展开为(2).

2, 当有”#”或”##”的时候

# A (2)

# STR(s) #s

# CONS(a,b) int(a##e##b)

(“int max: %s/n”, STR()); //

#

这行会被展开为:

(“int max: %s/n”, “”);

(“%s/n”, CONS(A, A)); // error

这一行则是:

(“%s/n”, int(AeA));

和A 都不会再被展开, 然而解决这个问题的方法很简单. 加

多一层中间转换宏.

加这层宏的用意是把所有宏的参数在中间层里全部展开, 那么在转换

宏里的那一个宏(_STR)就能得到正确的宏参数.

# A (2)

# _STR(s) #s

# STR(s) _STR(s) // 转换宏

# _CONS(a,b) int(a##e##b)

# CONS(a,b) _CONS(a,b) // 转换宏

(“int max: %s/n”, STR()); // ,int 型的最

大值,为一个变量 #

输出为: int max:

STR() –> _STR() 然后再转换成字符串;

(“%d/n”, CONS(A, A));

输出为:200

CONS(A, A) –> _CONS((2), (2)) –> int((2)e(2))

三、”#”和”##”的一些应用特例

1、合并匿名变量名

# (type, var, line) type var##line

# (type, line) (type,

, line)

# (type) (type, )

例:( int); 即: int ; 70 表

示该行行号;

第一层:( int); –> ( int,

);

第二层: –> ( int, , 70);

第三层: –> int ;

即每次只能解开当前层的宏,所以在第二层才能被解开;

2、填充结构

# FILL(a) {a, #a}

enum IDD{OPEN, CLOSE};

MSG{

IDD id;

const char * msg;

}MSG;

MSG _msg = {FILL(OPEN), FILL(CLOSE)};

相当于:

MSG _msg = {{OPEN, “OPEN”},

{CLOSE, “CLOSE”}};

3、记录文件名

# (f) #f

# (f) (f)

char = ();

4、得到一个数值类型所对应的字符串缓冲大小

# (type) #type

# (type) (type)

char buf

()

–> char buf

()

–> char buf

“”

这里相当于:

char buf;

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » 宏定义详解

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们