下面的代码中
for (pos = hlist_bl_first_rcu(head);
pos &&
({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; });
pos = rcu_dereference_raw(pos->next))
{
...
}
第3行 ({ tpos = hlist\_bl\_entry(pos, typeof(\*tpos), member); 1; })
的意思是执行函数 hlist\_bl\_entry()
后再将这个括号的值设置为 1
,就是这个 for
循环只通过 pos
的值来判断是否继续执行。
现在不太清楚这一行的语法,为什么可以这么写,求解释。
好吧,我替你找到出处了:linux 源码。
/**
* hlist_bl_for_each_entry_rcu - iterate over rcu list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_bl_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_bl_node within the struct.
*
*/
#define hlist_bl_for_each_entry_rcu(tpos, pos, head, member) \
for (pos = hlist_bl_first_rcu(head); \
pos && \
({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
pos = rcu_dereference_raw(pos->next))
#endif
这是 hlist_bl_for_each_entry_rcu
的定义。我们在对比一下 list_for_each_entry_rcu
的定义:
/**
* list_for_each_entry_rcu - iterate over rcu list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as list_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_entry_rcu(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(rcu_dereference(pos)->member.next), \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
pos &&
是短路求值,可以检查是否为空 NULL
,此时返回 1
,可以防止提前结束。
之前也没见到过这样的特殊用法,刚才搜了一下,找到了有关的描述。
({exp1; exp2; exp3;})
这样的用法是复合语句的表达式用法,其值等于exp3
的值。如果exp3
不能求值,得到的结果就是void
。
( {int a = 2+1; int b = 0; b;} ) // 0
( {int a = 2+1; int b = 0; int c = 0;} ) // void
我相信GNU C当中有更多标准化的描述,你也可以自己寻找。