Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541156
  • 博文数量: 78
  • 博客积分: 1913
  • 博客等级: 上尉
  • 技术积分: 829
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-14 21:29
文章分类

全部博文(78)

文章存档

2011年(27)

2010年(26)

2009年(20)

2008年(5)

我的朋友

分类: BSD

2011-07-29 13:16:56

C中如何使用宏属于编译器预处理的范畴,属于编译期概念。

<1>.宏定义中字符串化操作符#

#的功能是将其后面的宏参数进行字符串化操作,意思就是对它所应用的宏变量通过替换后在其左右各加上一个双引号。

例如:

#define WARN_IF(EXPR)\
do {\
if (EXPR)\
fprintf(stderr,
"Warning: " #EXPR "\n");\
}
while(0)

上面代码中的反斜线\主要用来转译换行符,即屏蔽换行符。

那么如下的代码调用:

WARN_IF(divider == 0);

将被解析为:

do {\
if (divider == 0)\
fprintf(stderr,
"Warning: " "divider == 0" "\n");\
}
while(0);

注意能够字符串化操作的必须是宏参数,不是随随便便的某个子串(token)都行的。 

<2>.宏定义中的连接符##

连接符##用来将两个token连接为一个token,但它不可以位于第一个token之前or最后一个token之后。注意这里连接的对象只要是token就行,而不一定是宏参数,但是##又必须位于宏定义中才有效,因其为编译期概念(比较绕)。

#define LINK_MULTIPLE(a, b, c, d) a##_##b##_##c##_##d
typedef
struct _record_type LINK_MULTIPLE(name, company, position, salary);
/*
* 上面的代码将被替换为
* typedef struct _record_type name_company_position_salary;
*/

又如下面的例子:

#define PARSER(N) printf("token" #N " = %d\n", token##N)

int token64 = 64;

如下调用宏:

PARSER(64);

将被解析为:

printf("token" "64" " = %d\n", token64);


在obj-c中,如果我有如下定义:
#define _X(A, B) (A#B)
#define _XX(A, B) _X([NSString stringWithFormat:@"%@_c", A], B)
gcc将报错!
正确的写法为:
#define _XX(A, B) _X(([NSString stringWithFormat:@"%@_c", A]), B)
阅读(2410) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

F.U.Moon2011-09-16 12:14:43

windflush: 这个和objective-c无关的吧,c语言也是这样的,这个应该是属于宏定义自身的规则.....
使用 Apple LLVM compiler 3.0居然没有报错了。

windflush2011-09-01 22:14:10

这个和objective-c无关的吧,c语言也是这样的,这个应该是属于宏定义自身的规则