Was Sie zwischen der Öffnung sehen ({
und })
Schließen ist ein Aussage Ausdruck - ein Nicht-Standard-Feature von GCC-Compiler, die eine zusammengesetzte Anweisungen in C-Ausdrücke einzubetten. Das Ergebnis eines solchen Anweisungsausdrucks ist die letzte Ausdrucksanweisung innerhalb der ({})
. In Ihrem Fall wäre das &__get_cpu_var(var)
.
Der Operator &
wird auf das Ergebnis von __get_cpu_var(var)
Teilausdruck angewendet. Das bedeutet, dass __get_cpu_var
einen Lvalue zurückgibt. Wenn dies in der Tat C ist, dann muss __get_cpu_var
auch ein Makro sein, da in C-Sprache Funktionen lvales nicht zurückgeben können.
Der Operator &
erzeugt einen Zeiger (das Ergebnis des gesamten Anweisungsausdrucks), der dann von einem *
-Operator dereferenziert wird, der zu Beginn der obigen Makrodefinition vorhanden ist. Das obige Makro entspricht also im Wesentlichen dem Ausdruck *&__get_cpu_var(var)
.
Einige könnten fragen, warum es als *&__get_cpu_var(var)
und nicht nur __get_cpu_var(var)
implementiert ist. Dies wird auf diese Weise erreicht, um das lvalueness des Ergebnisses von __get_cpu_var(var)
zu erhalten. Das Ergebnis eines Anweisungsausdrucks ist immer ein R-Wert, auch wenn der letzte Abschnitt in ({})
ein L-Wert ist. Um die Wertigkeit des Ergebnisses zu erhalten, wird der bekannte Trick *&
verwendet.
Dieser Trick ist in keiner Weise auf GCC-Anweisungsausdrücke beschränkt. Es wird relativ häufig in der alltäglichen C-Programmierung verwendet. Zum Beispiel stellen Sie sich zwei Variablen haben
int a, b;
und Sie möchten einen Ausdruck schreiben, die entweder a
oder b
als L-Wert zurückkehren würde (sagen wir, wir 42
es zuweisen möchten) in Abhängigkeit von der Auswahl Variable select
. Ein naiver Versuch aussehen könnte wie folgt
(select ? a : b) = 42;
Dies funktioniert nicht, da in C-Sprache der ?:
Bediener die lvalueness seiner Operanden verliert. Das Ergebnis ist ein rvalue, dem nicht zugeordnet werden kann. In dieser Situation kommt der *&
Trick zur Rettung
*(select ? &a : &b) = 42;
und jetzt funktioniert es wie beabsichtigt.
Dies ist genau, wie und warum die ursprüngliche Definition des Posters eine scheinbar redundante Anwendung von *
und &
enthält.Aufgrund der, dass Sie die oben get_cpu_var
Makro auf beiden Seiten von einem assgnment
something = get_cpu_var(something);
get_cpu_var(something) = something;
ohne diesen Trick verwenden können, würden Sie nur in der Lage sein get_cpu_var
auf der rechten Seite zu verwenden.
In C++ - Sprache wird der gleiche Effekt durch Verwendung von Referenzen erreicht. In C haben wir keine Referenzen, also verwenden wir stattdessen Tricks wie diese.
also ist das * (...) eine Typumwandlung zum Ergebnis? * edited.noted und danke. –
Also im Grunde diese gibt '* & __get_cpu_var (var)' - aber warum haben sie nicht einfach zurückgeben '__get_cpu_var (var)'? Irgendeine Art von Kompilierzeit Typprüfung? – Anthales
@Anthales: Ich habe die Antwort über – AnT