宏定义的一些情况分析

changing_better 2011-10-14 09:32:07
在内核代码中常遇到宏定义,有些不是太明白,有些查点资料也可以懂。先说说我自己明白的宏定义
1:宏中出现 \
例如
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
\ 表示换行符,一行命令写不完,可以使用换行符,换行符后面必须什么都不可以跟,空格也不行。
2:##宏定义会出现这个,看资料解释是字符合并的意思
这是合并操作符, 合并操作符##将出现在其左右的字符序列合并成一个标识符,例如:

#define CLASS_NAME(name) class##name
#define MERGE(x,y) x##y##x

则宏引用:
CLASS_NAME(systimer)
MERGE(me,to)
将分别扩展成如下两个标识符

classsystimer
metome
3: 这个宏定义请高手解释下函数 #define LIST_HEAD_INIT(name) { &(name), &(name) }
如果还有其他比较晦涩的宏定义,还请楼下补充学习下。
...全文
227 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
changing_better 2011-10-19
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 bhdgx 的回复:]

引用 18 楼 jay8830095 的回复:

引用 14 楼 wyfwx 的回复:

当心宏的副作用,不要写太复杂的宏

宏的副作用是说明啊?见过这样的东西
例如
#define MIN(a,b) ((a)<=(b)?(a):(b))
如果这样使用
MIN(++p,c)会出现副作用,请能分析下吗?

p增加了2
[/Quote]
可以详细分析下吧,什么时候增加俩次的。
changing_better 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 zhao4zhong1 的回复:]

编译选项加/EP /P,重新编译,查看宏展开后对应的.i文件。
[/Quote]
不好意思,赵老师,我这是内核代码。不好编译展开,完全不懂.i文件是什么东西。
condlover 2011-10-14
  • 打赏
  • 举报
回复
楼主用心 了 顶一下
赵4老师 2011-10-14
  • 打赏
  • 举报
回复
编译选项加/EP /P,重新编译,查看宏展开后对应的.i文件。
Soulic 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 jay8830095 的回复:]

引用 14 楼 wyfwx 的回复:

当心宏的副作用,不要写太复杂的宏

宏的副作用是说明啊?见过这样的东西
例如
#define MIN(a,b) ((a)<=(b)?(a):(b))
如果这样使用
MIN(++p,c)会出现副作用,请能分析下吗?
[/Quote]
p增加了2
changing_better 2011-10-14
  • 打赏
  • 举报
回复
对头,我误认为是什么逗号表达式了。。。,看来自己写出来比较好理解,2楼有点不对哦,char*指针不可以指向struct的吧
btloveet 2011-10-14
  • 打赏
  • 举报
回复
学习了额!
满衣兄 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jay8830095 的回复:]

#define LIST_HEAD_INIT(name) { &(name), &(name) }
这个宏到底什么意思呢?
宏所处的环境是
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(……
[/Quote]
这样应该是定义链表的。
struct list_head node = LIST_HEAD_INIT(node)相当于:
struct list_head node = { &(node), &(node) }也就是说next, prev都指向node
贪食蛇男 2011-10-14
  • 打赏
  • 举报
回复
我个人用宏主要是为了大量减少代码编写,因为好多代码几乎一模一样。比如分配多块内存并检查内存是否分配成功的地方,就大量使用:
xxx = (char*)malloc(size);
if(!xxx)
{
return;
}
memset(xxx, 0, size);
这种,直接定义个宏就比较方便。
我的工程里的一段代码:

#define SET_STRA(str, member, action) \
FREE_STR(member); \
if(!str) \
{ \
action; \
} \
int len = strlen(str); \
if(!len) \
{ \
action; \
} \
member = (char*)malloc(len + 1); \
if(!member) \
{ \
action; \
} \
memset(member, 0, len + 1); \
strcat(member, str); \

#define SET_STRW(str, member, action) \
FREE_STR(member); \
if(!str) \
{ \
action; \
} \
int len = wcslen(str); \
if(!len) \
{ \
action; \
} \
member = (wchar_t*)malloc((len + 1) * sizeof(wchar_t)); \
if(!member) \
{ \
action; \
} \
memset(member, 0, (len + 1) * sizeof(wchar_t)); \
wcscat(member, str); \

#define DEF_SETSTRA(cls, str, member, Member) \
void cls::Set##Member##A(LPCSTR str) \
{ \
const wchar_t* wStr = AToW(str); \
do \
{ \
SET_STRW(wStr, member, break); \
} while (FALSE); \
FREE_BUFF(wStr); \
} \

#define DEF_SETSTRW(cls, str, member, Member) \
void cls::Set##Member##W(LPCWSTR str) \
{ \
SET_STRW(str, member, return); \
} \

#define DEF_SETSTRU(cls, str, member, Member) \
void cls::Set##Member##U(LPCSTR str) \
{ \
const wchar_t* wStr = UToW(str); \
do \
{ \
SET_STRW(wStr, member, break); \
} while(FALSE); \
FREE_BUFF(wStr); \
} \

#define DEF_SETSTR(cls, str, member, Member) \
DEF_SETSTRA(cls, str, member, Member) \
DEF_SETSTRW(cls, str, member, Member) \
DEF_SETSTRU(cls, str, member, Member) \
acdbxzyw 2011-10-14
  • 打赏
  • 举报
回复
这就是初始化 list head.
把 next 和 prev 都指向 name.
满衣兄 2011-10-14
  • 打赏
  • 举报
回复
#define LIST_HEAD_INIT(name) { &(name), &(name) }用来初始化结构体的
struct list_head name = LIST_HEAD_INIT(name)相当于:
struct list_head name = { &(name), &(name) }
例如:list_head结构体可能是这么定义的:
struct list_head
{
char* a;
char* b;
};
那么可以这样声明一个结构体:
struct list_head test = { &(test), &(test) }
表示a,b都指向结构体的首地址。
changing_better 2011-10-14
  • 打赏
  • 举报
回复
#define LIST_HEAD_INIT(name) { &(name), &(name) }
这个宏到底什么意思呢?
宏所处的环境是
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
例如我在其他地方调用LIST_HEAD(a),会出现什么情况。
AndyZhang 2011-10-14
  • 打赏
  • 举报
回复
{这里可以初始化,就像初始化数组一样啊}
changing_better 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wyfwx 的回复:]

当心宏的副作用,不要写太复杂的宏
[/Quote]
宏的副作用是说明啊?见过这样的东西
例如
#define MIN(a,b) ((a)<=(b)?(a):(b))
如果这样使用
MIN(++p,c)会出现副作用,请能分析下吗?
babaluoshahao 2011-10-14
  • 打赏
  • 举报
回复
学习 下……
Qlaiaqu 2011-10-14
  • 打赏
  • 举报
回复
宏展开之后才会进行词法分析和语法分析,所以宏展开是可以做的,既然是内核
gcc -E test.c
就可以看到宏展开的数据了
proorck6 2011-10-14
  • 打赏
  • 举报
回复
学习了
wyfwx 2011-10-14
  • 打赏
  • 举报
回复
当心宏的副作用,不要写太复杂的宏
changing_better 2011-10-14
  • 打赏
  • 举报
回复
分析开了就不晦涩了,这需要个过程。
qq120848369 2011-10-14
  • 打赏
  • 举报
回复
这个真不晦涩,gcc -E看一下替换后结果不就得了。

struct A
{
int a,b;
}a={1,2};

这不是很正常么。
加载更多回复(1)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧