文章目录
- 先放结论
- 废话
- `({})`复合表达式介绍
- 最后的废话
先放结论
({子表达式1;子表达式2;})是GNU C中的一个拓展,返回值是最后一个表达式的返回值,也就是子表达式2的返回值。
废话
这个表达式是在看Linux源码的时候发现的(内核小白随便翻看到的)。
// llist.c
bool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
struct llist_head *head)
{
struct llist_node *first = READ_ONCE(head->first);
do {
new_last->next = first;
} while (!try_cmpxchg(&head->first, &first, new_first));
return !first;
}
#define try_cmpxchg(ptr, oldp, ...) \
({ \
typeof(ptr) __ai_ptr = (ptr); \
typeof(oldp) __ai_oldp = (oldp); \
kcsan_mb(); \
instrument_a
tomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \
instrument_read_write(__ai_oldp, sizeof(*__ai_oldp)); \
raw_try_cmpxchg(__ai_ptr, __ai_oldp, __VA_ARGS__); \
})
#define raw_try_cmpxchg(_ptr, _oldp, _new) \
({ \
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
___r = raw_cmpxchg((_ptr), ___o, (_new)); \
if (unlikely(___r != ___o)) \
*___op = ___r; \
likely(___r == ___o); \
})
从第一个代码块可以看到!try_cmpxchg(...)
,进行了一个逻辑取反操作,而try_cmpxchg
是一个用圆括号括起来的代码块,它能取反说明它肯定等价于一个有返回值的表达式,于是有了一下几个猜想
;
和,
一样是一个特殊运算符,表达式的值是最后一个值{}
有返回值,返回值等价于最后一个表达式()
有特殊用法,或者({})
是一种特殊的语法
经过实验,1、2均不符合实验结果,而且在cppreferece.com也没有查询到;
运算符,也没说到复合语句(代码块)有返回值,而且单独使用{}
也取不出返回值,只有({})
才会存在值。
({})
复合表达式介绍
({})
是GNU C的一个拓展用法(我在标准C没找到相关用法),把复合语句(代码块)用圆括号括起来,其值是最后一个表达式的值。
文档中说代码块的最后应该是一个以;
结尾的表达式,这个子表达式用作整个结构的值。
最后的废话
这个结构应该是GNU C的拓展用法,如果不是希望评论指正,这个结构我看到在宏函数里面用得很多。表达式的值是代码块内最后一个表达式的值。