你开口({
闭})
之间看到什么是语句表达 - GCC编译器,它允许一个嵌入化合物语句转换为C表达式的非标准的特征。这种表达式的结果是({})
中的最后一个表达式语句。在你的情况下,将是&__get_cpu_var(var)
。
&
运算符适用于__get_cpu_var(var)
子表达式的结果。这意味着__get_cpu_var
返回一个左值。如果这确实是C,那么__get_cpu_var
也必须是宏,因为在C语言中函数不能返回左值。
&
运算符产生一个指针(整个语句表达式的结果),然后由上面宏定义开头的*
运算符取消引用。所以,上面的宏基本上等于*&__get_cpu_var(var)
表达式。
有人可能会问为什么它实现为*&__get_cpu_var(var)
而不仅仅是__get_cpu_var(var)
。这样做是为了保留__get_cpu_var(var)
结果的。语句表达式的结果总是一个右值,即使({})
内的最后一步是左值。为了保持结果的公正性,使用了熟知的*&
技巧。
这个技巧并不限于GCC语句表达式。它比较常用于日常的C编程。例如,假设你有两个变量
int a, b;
和你想写,将返回要么a
或b
作为左值表达式(假设我们想给42
的话)取决于选择的变量select
。一个天真的尝试可能如下
(select ? a : b) = 42;
这在C语言中是行不通的,因为?:
运营商失去了它的操作数的lvalueness。结果是一个不能分配的右值。在这种情况下*&
技巧来拯救
*(select ? &a : &b) = 42;
现在它按预期工作。
这就是如何以及为什么楼主的宏定义包含*
和&
一个看似多余的应用程序。因为,你可以用两边的上方get_cpu_var
宏观的assgnment
something = get_cpu_var(something);
get_cpu_var(something) = something;
没有那招你只能在右侧使用get_cpu_var
。
在C++语言中,使用引用可以获得相同的效果。在C中我们没有引用,所以我们使用这样的技巧来代替。
来源
2012-04-15 21:35:21
AnT
所以*(...)是结果的类型转换吗? *编辑。注意和谢谢。 – 2012-04-15 21:36:54
所以这基本上返回'*&__get_cpu_var(var)' - 但他们为什么不简单地返回'__get_cpu_var(var)'?某种编译时类型检查? – Anthales 2012-04-15 21:42:55
@Anthales:我在上面加了 – AnT 2012-04-15 21:51:16