C中的复合语句总结

时间:2023-02-05 02:19:11

C中表达式和复合语句的如下:

({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
int a = ({ int b = 8;  
int c = 99;
b + c;
b + c - 10;
});

printf("a = %d\n", a);

输入a的值为97;

这类复合语句(Statements and Declarations in Expressions)在linux kernel中的经常使用到使用,且用于宏定义。
简单例子如下:

/* linux-2.6.38.8/include/linux/kernel.h */  
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })

/* linux-2.6.38.8/include/linux/kernel.h *
* min_not_zero - return the minimum that is _not_ zero, unless both are zero
* @x: value1
* @y: value2
*/
#define min_not_zero(x, y) ({ \
typeof(x) __x = (x); \
typeof(y) __y = (y); \
__x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })

复杂的例子如:

/**
* 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,可以防止提前结束。