宏定义

常见的宏定义有两种,不带参数的宏定义和带参数的宏定义。

无参宏定义

无参数宏定义的格式为:
#define 标识符 替换列表
替换列表可以是数值常量、字符常量、字符串常量等,故可以把宏定义理解为使用标识符表示一常量,或称符号常量。

说明:

  1. 可以不在行首,但只允许它前面有空格符。例如:

#define PI 3.1416 //正确,该行#前允许有空格
 int a;#define N 5 //错误,该行#前不允许有空格外的其他字符
  1. 标识符和替换列表之间不能加赋值号 =,替换列表后不能加分号
#define N =5 //虽语法正确,但预处理器会把N替换成=5
int a[N]; //错误,因为宏替换之后为 int a[=5];

宏定义不是语句,是预处理指令,故结尾不加分号。如果不小心添加了分号,虽然有时该宏定义没问题,但在宏替换时,可能导致 C 语法错误,或得不到预期结果。例如:

#define N 5; //虽语法正确,但会把N替换成5;
int a[N]; //语法错误,宏替换后,为int a[5;];错误
  1. 由于宏定义仅是做简单的文本替换,故替换列表中如有表达式,必须把该表达式用括号括起来,否则可能会出现逻辑上的“错误”。例如:
#define N 3+2
int r=N*N;

宏替换后为:

int r=3+2*3+2; //r=11

如果采用如下形式的宏定义:

#define N (3+2)
int r=N*N;

则宏替换后,为:

int r=(3+2)*(3+2); //r=25
  1. 当替换列表一行写不下时,可以使用反斜线\作为续行符延续到下一行。例如:
#define USA "The United \
States of \
America"

该宏定义中替换列表为字符串常量,如果该串较长,或为了使替换列表的结构更清晰,可使用续行符 \ 把该串分若干行来写,除最后一行外,每行行尾都必须加续行符 \。

带参宏定义

带参数的宏定义格式为:
#define 标识符(参数1,参数2,...,参数n) 替换列表

例如,求两个参数中最大值的带参宏定义为:

#define MAX(a,b) ((a)>(b)?(a) : (b))

当有如下语句时

int c=MAX(5,3);

预处理器会将带参数的宏替换成如下形式:

int c=((5)>(3)?(5) : (3));

故计算结果c=5。
说明:

  1. 标识符与参数表的左括号之间不能有空格,否则预处理器会把该宏理解为普通的无参宏定义,故以下是错误的带参宏定义形式
#define MAX (a,b) ( (a) > (b) ? (a) : (b) ) //错误的带参宏定义格式
  1. 宏替换列表中每个参数及整个替换列表,都必须用一对小括号 () 括起来,否则可能会出现歧义。
    【例 1】以下程序试图定义求两个参数乘积的宏定义,欲使用该宏求 3 与 6 的乘积,分析该程序能否实现预期功能,如果不能,请给出修改方案。
#include <stdio.h>
#define MUL(a,b) (a*b)
int main (void)
{
    int c;
    c=MUL(3,5+1);
    printf("c=%d\n",c);
    return 0;
}

分析:

  1. 由于该宏定义中的替换列表中的参数没有加括号,故宏调用时,如果参数是个表达式,可能会出现歧义,得不到预期结果。

本例中宏调用 c=MUL(3,5+1); 会替换成 c=(3*5+1)=16;,与预期功能不符。

  1. 虽然把宏调用时的参数 5+1 括起来,可达到题目要求的效果,但这属于治标不治本。为统一编程规范,把替换列表中的每个参数均加括号,整个替换列表也加括号。

同时,为达到标本兼治,在宏定义时,除单一值参数外,应显式加括号。

修改代码为:

#include <stdio.h>
#define MUL(a,b) ((a)*(b))//修改处1
int main (void)
{
    int c;
    c=MUL(3,(5+1);//修改处2
    printf("c=%d\n",c);
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值