我很想知道在以下赋值操作中对filp
和x
指针使用括号:
#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
答案 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)
别忘了提到这是功能宏扩展的一部分。如果传入的表达式很复杂,这些参数应该始终用括号括起来以避免错误。