The get_cpu_var marcro which is defined as below
29 #define get_cpu_var(var) (*({ \
30 extern int simple_identifier_##var(void); \
31 preempt_disable(); \
32 &__get_cpu_var(var); }))
seems incomprehensible to be.I am supposing it was one kind of function macro which return a variable pointer(based on the asterisk) or is it some kind of function pointer.Am I even close to it?Could anyone enlighten me?
esoteric, perplexing, abstract, complex, complicated, deep, enigmatic, heavy, hidden, incomprehensible, intricate, involved, muddy, obscure, profound, puzzling, recondite, subtle, unfathomable, vague.
Abstruse means difficult to understand; obscure. Obtuse refers to an angle exceeding 90 degrees but less than 180 degrees. It also can refer to someone who is slow to understand, lacking sharpness or quickness of intellect.
Abstruse is used to describe things that aren't easily accessible to the lay reader or average person. Specifically, it suggests the use of language or other material that suits the advanced levels of a subject of which the rest of us might have only an elementary understanding.
The abstruse imagery of his work has produced a large corpus of diverging interpretations. No financial statement was too intricate for her, and no contract too abstruse. Among the words, many are unusual and some are abstruse. Some critics disliked the abstruse plot and deliberately enigmatic ending.
What you see between the opening ({
and closing })
is a statement expression - a non-standard feature of GCC compiler, which allows one to embed compound statements into C expressions. The result of such statement expression is the very last expression statement inside the ({})
. In your case that would be &__get_cpu_var(var)
.
The &
operator is applied to the result of __get_cpu_var(var)
subexpression. That implies that __get_cpu_var
returns an lvalue. If this is indeed C, then __get_cpu_var
must also be a macro, since in C language functions cannot return lvalues.
The &
operator produces a pointer (the result of the entire statement expression), which is then dereferenced by a *
operator present at the very beginning of the above macro definition. So, the above macro is essentially equivalent to the *&__get_cpu_var(var)
expression.
Some might ask why it is implemented as *&__get_cpu_var(var)
and not just __get_cpu_var(var)
. This is done that way to preserve the lvalueness of the result of __get_cpu_var(var)
. The result of statement expression is always an rvalue, even if the last stetement inside the ({})
was an lvalue. In order to preserve the lvalueness of the result the well-known *&
trick is used.
This trick is not limited to GCC statement expressions in any way. It is relatively often used in ordinary everyday C programming. For example, imagine you have two variables
int a, b;
and you want to write an expression that would return either a
or b
as an lvalue (let's say we want to assign 42
to it) depending on the selector variable select
. A naive attempt might look as follows
(select ? a : b) = 42;
This will not work, since in C language the ?:
operator loses the lvalueness of its operands. The result is an rvalue, which cannot be assigned to. In this situation the *&
trick comes to the rescue
*(select ? &a : &b) = 42;
and now it works as intended.
This is exactly how and why the original poster's macro definition contains a seemingly redundant application of *
and &
. Because of that you can use the above get_cpu_var
macro on either side of an assgnment
something = get_cpu_var(something);
get_cpu_var(something) = something;
without that trick you'd only be able to use get_cpu_var
on the right-hand side.
In C++ language the same effect is achieved by using references. In C we have no references, so we use tricks like this instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With