在宏中使用括号的目的

时间:2014-07-11 08:12:23

标签: c linux macros

我很想知道在以下赋值操作中对filpx指针使用括号:

#define init_sync_kiocb(x, filp) \
do { \
struct task_struct *tsk = current; \
(x)->ki_flags = 0; \
(x)->ki_users = 1; \
(x)->ki_key = KIOCB_SYNC_KEY; \
(x)->ki_filp = (filp); \        // This line here
....
....

来源: https://github.com/gp-b2g/gp-peak-kernel/blob/master/include/linux/aio.h#L135

4 个答案:

答案 0 :(得分:4)

这些用于宏定义,由预处理器作为文本替换处理。它是文本替换的事实可能导致奇怪的表达。考虑:

p = &a_struct_array[10];
init_sync_kiocb(p + 20, filp)
没有parens,它变成了:

p + 20->ki_filp = (filp); 

与parens:

(p + 20)->ki_filp = (filp);

我不能,但我敢打赌也可以找到类似的例子,或者至少你永远不知道。

答案 1 :(得分:2)

左侧只是典型的安全措施,因为x是一个宏参数。除非“需要成为结构指针的东西”受到保护,否则它可能扩展为使->运算符失败的东西。

右手边对我来说不太明显,但可能只是出于一致性和对称性的原因;始终用括号保护宏参数。有些人认为这是一个严格的规则,也许该项目的风格指南也是如此。

答案 2 :(得分:2)

它在宏内。这是常见的好习惯。想象一下,你可以调用宏init_sync_kiocb,例如。

init_sync_kiocb(pp?*pp:&x,fil?fil:somfil+1);

用括号将其扩展为

(pp?*pp:&x)->ki_filp = (fil?fil:somfil+1);

没有括号,宏扩展会出错(输入错误或解析错误):

pp?*pp:&x->ki_filp = fil?fil:somfil+1;

答案 3 :(得分:1)

别忘了提到这是功能宏扩展的一部分。如果传入的表达式很复杂,这些参数应该始终用括号括起来以避免错误。