sack-tvt
宏定义有
无参数宏定义
和
带参数宏定义
两种。
无参数的宏定义的一般形式为
# define
标识符
字符序列
其中
# define
之后的标识符称
为宏定义名
(
简称宏名
)
,要求宏名与字符序列之间用空格符分
隔。
这种宏定
义要求编译预处理程序将源程序中随后所有的定名的出现
(
注释
与字符串常量中
的除外
)
均用字符序列
替换之。前面经常使用的定义符号常量是宏定义的最简单应用。如有:
# define TRUE 1
# define FALSE 0
则在定义它们的源程序文件中,凡定义之后出现的
单词
TRUE
将用
1
< br>替代之;出现单词
FALSE
将用
0
替代之。
在宏定义的#之前可以有若干个空格、
制表符,
但不允许有其它字符。
宏定义在源程
序中单独另起一行,换行
符是宏定义的结束标志。如果一个宏定义太长,一行不
够时,
可采
用续行的方法。续行是在键人回车符之前先键入符号
。注意回车要紧接在符号
之后,
中间不能插入其它符号。
宏定义的有效范围称为宏定义名的辖域,
辖域从宏定义的定义结
束处开始到其所在的
源程序文件末尾。宏定义名的辖域不受分程序结构的影响。
可以用预处理命令
#undef
终止宏
定义名的辖域。
在新的宏定义中,可以使用前面已定义的宏名。例如,
# define R 2.5
# define PI 3.1415926
#
define Circle 2*PI*R
#
define Area PI* R * R
程序中的
Ci
rcle
被展开为
2*3.1415926*
2.5
,
Area
被展开为
3.1415926*2.5*2.5
。
如有必要,宏名可被重复定义。被重复定义后,宏名
原先的意义被新意义所代替。
< br>通常,无参数的宏定义多用于定义常量。程序中统一用宏名表示常量值,便于程序前
后统一,不易出错,也便于修改,能提高程序的可读性和可移植性。特别是给数组元素个数
一个宏定义,并用宏名定义数组元素个数能部分弥补数组元素个数固定的不足。
注意:
预处理程序在处理
宏定义时
,
只作字符序列的替换工作,
不作任何语法的检查。
如果宏定义不当,错误要到预处理之后的编译阶段才能发现。宏定
义以换行结束,不需要分
号等符号作分隔符。如有以下定定义:
# define PI
3.1415926
;
原希望用
p>
PI
求圆的周长的语句
c
=
2*PI*r
;
经宏展开后,变成
c
=
2*3.1415926*
r
;
这就不能达到希望的要求。
带参数宏定义进一步扩充了无参数宏定义的能力,在字符序列
替换同时还能进行参数替
换。带参数定定义的一般形式为
# define
标识符
(<
/p>
参数表
)
字符序列
其中参数表中的参数之间用逗号分隔,
字符序列中应包含参
数表中的参数。
在定义带参数的
宏时,
宏名标识符与左圆括号之间不允许有空白符,
应紧接在一起,
否
则变成了无参数的宏
定义。
如有宏定义:
# define
MAX(A
,
B) ((A) > (B)?(A):(B))
则代码
y
=
MAX(
p
+
q
,
u+v)
将被替换成
y
=
((p
+
q) >(u
+
v)?(p
+
q):(u
+
v)
。
程序中的宏调用是这样被替换展开的,
分别用宏调用中的实在参数字符序列
(
如
p
+
q
和<
/p>
u
+
V)
替换
宏定义字符序列中对应所有出现的形式参数
(
如用
p
+
q
替代所有形式参
p>
数
A
,
用
u
+
V
替代所有形式参
数
B)
,
而宏定义字符序列中的不是形
式参数的其它字
符则保
留。这样形成
的字符序列,即为宏调用的展开替换结果。
宏调用提供的实在参数个数必须与
宏定义中的形式参数个数相同。
注意:宏调用与函数调用的区别。函数调用在程序运行时实行,而宏展开是在编译
的预处理阶段进行;函数调用占用程序运行时间,宏调用只占编译时间;函数调用
对实参
有类型要求,
而宏
调用实在参数与宏定义形式参数之间没有类型的概念,
只有字符序列的对
应关系。函数调用可返回一个值,宏调用获得希望的
C
代码。另
外,函数调用时,实参表
达
式分别独立求值在前,执行函数体在后。宏调用是实在参数字符序列替换形式参数。替换
后,实在参数字符序列就与相邻的字符自然连
接,实在参数的
独立性就不一定依旧存在。
如下面的宏定义:
# define SQR(x) x*x
希望实现表达式的平方计算。对于宏调用
P
=
SQR(y)
能得到希望的宏展开
p
=
y*y
。但对于宏调用
q
=
SQR(u
+
v)
得到的
宏展开是
q
=
u
+
V*u
+
V
。
显然,后者的展开结果不是程序设计者所希望的。为能保持实在参数替换后的独立性
,应在
宏定义中给形式参数加上括号。进一步,为了保证宏调用的独立性,作为算式的宏
定义也应
加括
号。如
SQR
宏定义改写成:
#
define SQR((x)*(x))
才是正确的宏定义。
<
/p>
对于简短的表达式计算函数,或为了提高程序的执行效率、避免函数调用时的分配
存储单元、保留现场、参数值传递、释放存储单元等工作。可将函数定义改写成宏定义。所
以合理使用宏定义,可以使程序更简洁。
使用一些宏跟踪调试
A N S I
标准
说明了五个预定义
的宏名。它们是:
_ L I N E _ (
两个下划线
)
,对应
%d
_ F I L E _
对应
%s
_ D A T E _
对应
%s
_ T I M E _
对应
%s
_ S T D C _
如果编译不是标准的
,
则可能仅支持以
上宏名中的几个
,
或根本不支持。记住编译程序
也许还提供其它预定义的宏名。
_ L I N E _
及
_ F I
L E _
宏指令在有关
# l i n e
< br>的部分中已讨论
,
这里讨论其余的宏名。
_ D AT E _
宏指令含有形式为月
/
日
/
年的串
,
表示源文件被翻译到代码时的日期。
源代码翻译到目标代码的时间作为串包含在
_ T I M E
_
中。串形式为时:分:秒。
如果
实现是标准的
,
则宏
_ S T D
C _
含有十进制常量
1
。如果它含有
任何其它数
,
则实现是
非标准的。
可以定义宏
,
例如
:
当定义了<
/p>
_DEBUG,
输出数据信息和所在文件所在行
< br>
#ifdef _DEBUG
#define
DEBUGMSG(msg,date)
printf(msg);printf(“%d%d%s”,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
20,
宏定义防止使用是错误
用小括号包含。
例如:
#define ADD(a,b)
(
a+b
)
sack-tvt
sack-tvt
sack-tvt
sack-tvt
sack-tvt
sack-tvt
sack-tvt
sack-tvt
-
上一篇:物流术语_中英文
下一篇:懂你英语 Level3 Unit2 Part3