设为首页 加入收藏

TOP

C语言"#","#@"和"##"在宏定义中的使用技巧
2015-01-22 22:42:53 来源: 作者: 【 】 浏览:94
Tags:语言 " #" #@" ##" 定义 使用技巧

?? C语言博大精深,每一个细节都蕴含者着很多技巧特性,相信C程序员的同行首次遇到"#","#@"和"##"之类的技巧时也是不知所云。本文总结"#","#@"和"##"在宏定义中的使用技巧,收集于网络!以备需要时查阅,并希望能帮助其他同行。

一、一般用法

#把宏参数变为一个字符串,#@把宏参数变为一个字符,##把两个宏参数贴合在一起。

?#include

#include

#define STR(s)??????? #s??????????????????? // #与参数之间可以有空格

#define TOCHAR(c)?????? #@c?????????

#define CONS(a,b)? int(a##e##b)???? // ##与参数之间可以有空格

int main(void)

{

??? printf(STR(pele));?????????????? // 输出字符串"pele"

??? printf("%c\n",TOCHAR(z));? // 输出字符z

??? printf("%d\n",CONS(2,3));?? // 2e3 输出:2000

??? return 0;

}

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

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

#define A?????????????? (2)

#define STR(s)??????? #s

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

?

printf("int max: %s\n", STR(INT_MAX));

这行会被展开为:

printf("int max: %s\n","INT_MAX");

printf("%s\n", CONS(A, A));?

这一行被展开为:

printf("%s\n", int(AeA));

?

INT_MAX和A都不会再被展开,然而解决这个问题的方法很简单,多加一层中间转换宏。加这层宏的用意是把所有宏的参数在这层里全部展开,那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数。

#define A???????????????? (2)

#define _STR(s)??????? #s

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

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

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

?


printf("int max: %s\n",STR(INT_MAX));

输出为:int max: 0x7fffffff

STR(INT_MAX)? --> _STR(0x7fffffff)? --> "0x7fffffff"

?

printf("%d\n", CONS(A, A));

输出为:200

CONS(A, A)? -->? _CONS((2), (2)) --> int((2)e(2))

?

以下为Minix操作系统相关的源代码:

#ifdef?? _ANSI

#define?? __str(x)?????? # x

#define??? __xstr(x)??? __str(x)??????? //转换宏

_PROTOTYPE( void __bad_assertion, (const char*_mess) );

#define?? assert(expr)((expr)?(void)0 : \

???????????????????????????????? __bad_assertion("Assertion \"" #expr \

????????????????????????????????? "\" failed, file " __xstr(__FILE__) \

????????????????????????????????? ", line " __xstr(__LINE__) "\n"))

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

1、合并匿名变量名

#define? ___ANONYMOUS1(type, var, line)??? type? var##line

#define? __ANONYMOUS0(type, line)???????????? ___ANONYMOUS1(type, _anonymous, line)

#define? ANONYMOUS(type)???????????????????????? __ANONYMOUS0(type, __LINE__)

例:ANONYMOUS(static int);? 即: static int _anonymous70;? 70表示该行行号;

第一层:ANONYMOUS(static int);? -->? __ANONYMOUS0(staticint, __LINE__);

第二层:?????????????????????? -->? ___ANONYMOUS1(static int, _anonymous,70);

第三层:?????????????????????? -->? static int? _anonymous70;

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

?

2、填充结构

#define? FILL(a)?? {a, #a}

enum IDD{OPEN, CLOSE};

typedef struct MSG

{

?? IDD id;

?? const char * msg;

}MSG;

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

相当于:

MSG _msg[] = {{OPEN, "OPEN"}, {CLOSE,"CLOSE"}};

?

3、记录文件名

#define? _GET_FILE_NAME(f)?? #f

#define? GET_FILE_NAME(f)?? _GET_FILE_NAME(f)?????? //转换宏

static char? FILE_NAME[] =GET_FILE_NAME(__FILE__);

?

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

#define? _TYPE_BUF_SIZE(type)? sizeof#type

#define? TYPE_BUF_SIZE(type)? _TYPE_BUF_SIZE(type)

char? buf[TYPE_BUF_SIZE(INT_MAX)];

???? -->? char buf[_TYPE_BUF_SIZE(0x7fffffff)];

???? -->? char buf[sizeof "0x7fffffff"];

这里相当于:

char? buf[11];

?

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇【知其所以然】语义"陷阱&qu.. 下一篇#include <iostream>与#inc..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: