define 中的“ # 运算符”和“ ## 运算符”

1.利用宏参数创建字符串:# 运算符

在类函数宏(function-like macro)的替换部分中,“#”符号用作一个预处理运算符,它可以把语言符号(token)转化为字符串。例如,如果 x 是一个宏参量,那么 #x 可以把参数名转化为相应的字符串。该过程称为字符串化

#include <stdio.h> 
#define PSQR(x) printf("The square of " #x " is %d. /r/n", (x) * (x)) 
int main(void)
{
    int y = 5; 
    
    PSQR(y);
    PSQR(2 + 4); 
 
    return 0; 
}
// 输出:
The square of y is 25.     // 用 "y" 代替 #x 
The square of 2 + 4 is 36. // 用 "2 + 4" 代替 #x

2. 预处理器的粘合剂:## 运算符

和 # 运算符一样,## 运算符可以用于类函数宏的替换部分。另外,## 运算符还可用于类对象宏(object-like macro)的替换部分。这个运算符把两个语言符号组合成单个语言符号。例如,可以定义如下宏:

#define XNAME(n) x ## n  

 宏调用 XNAME(4) 会展开成 x4 。
说明:类对象宏就是用来代表值的宏。如,#define PI 3.141593 中的PI。

#include <stdio.h> 
#define XNAME(n) x ## n 
#define PRINT_XN(n) printf("x" #n " = %d/r/n", x ## n); 
int main(void)
{
    int XNAME(1) = 14; // 变为 int x1 = 14; 
    int XNAME(2) = 20; // 变为 int x2 = 20; 
    PRINT_XN(1)        // 变为 printf("x1 = %d/r/n", x1); 
    PRINT_XN(2)        // 变为 printf("x2 = %d/r/n", x2); 
 
    return 0; 
}
// 输出:
x1 = 14 
x2 = 20 

语言符号

从技术方面看,系统把宏的主体当作语言符号(token)类型字符串,而不是字符型字符串。C 预处理器中的语言符号是宏定义主体中的单独的“词(word)”。用空白字符把这些词分开。例如:

#define FOUR 2*2

 这个定义中有一个语言符号:即序列 2*2 。但是:

#define SIX 2 * 3

 这个定义中有一个语言符号:即序列 2*2 。但是:

#define SIX 2 * 3

 这个定义中有三个语言符号:2、* 和 3 。
在处理主体中的多个空格时,字符型字符串和语言符号型字符串采用不同方法。考虑下面的定义:

#define EIGHT 4    *    8

 把主体解释为字符时,预处理器用4 * 8替换EIGHT。也就是说,额外的空格也当作替换文本的一部分。但是,当把主体解释为语言符号类型时,预处理器用单个空格分隔的三个语言符号,即4 * 8来替换EIGHI。换句话说,用字符型字符串的观点看,空格也是主体的一部分;而用语言符号字符串的观点看,空格只是分隔主体中语言符号的符号。在实际应用中,有些 C 编译器把宏主体当作字符串而非语言符号。在比这个实例更复杂的情况下,字符与语言符号之间的差异才有实际意义。
顺便提一下,C 编译器处理语言符号的方式比预处理器的处理方式更加复杂。编译器能理解 C 的规则,不需要用空格来分隔语言符号。例如,C 编译器把 2*2 当作三个语言符号。原因是 C 编译器认为每个 2 都是一个常量,而 * 是一个运算符。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值