Wenn + 0
nicht verwendet wird, wäre es ein lvalue, dem Sie versehentlich zuweisen könnten, z. B.
if (atomic_read(v) = 42) {
...
}
würde "funktionieren"... Statt + 0
Sie könnten einfach unäres +
verwenden , also
(+(v)->counter)
Jedoch + 0
hat eine guter Vorteil gegenüber +
im allgemeinen Fall:+
erfordert, dass das Argument ein arithmetischer Typ ist - aber Zeiger sind nicht vom arithmetischen Typ. Noch + 0
würde für Zeiger gleichermaßen funktionieren (und für Zeiger allein können Sie &*
verwenden um lvalue in einen Wert von expression umzuwandeln; dies funktioniert garantiert sogar für Nullzeiger)
Es ist möglich, dass die + 0
wurde hinzugefügt, damit der Compiler eine Diagnose ausgibt, falls es eine Neudefinition der funktionsähnlichen Makros atomic_read
gab und atomic64_read
.
Gemäß dem C-Standard ist es möglich, einen Bezeichner, der ein funktionsähnliches Makro ist, neu zu definieren, wenn die zweite Definition ein ebenfalls funktionsähnliches Makro ist, das dieselbe Anzahl und Schreibweise von Parametern hat und die beiden Ersetzungslisten identisch sind.
Aus C11-Standard (n1570), Abschnitt 6.10.3/2:
... Ebenso darf ein derzeit als funktionsähnliches Makro definierter Bezeichner nicht durch einen anderen #define
umdefiniert werden Vorverarbeitungsanweisung, es sei denn, die zweite Definition ist eine funktionsähnliche Makrodefinition mit derselben Anzahl und Schreibweise von Parametern und die beiden Ersetzungslisten sind identisch.
Die Kernel-Version (2.6.26) ist ziemlich alt, aber ein ähnliches Verbot einer solchen Neudefinition kann in älteren Standards bis hin zum C89-Standard gefunden werden.
Aktuell sind die Makros atomic_read
und atomic64_read
sind in der Datei atomic.h
definiert .
Wenn der Benutzer sie in einer Quelldatei wie folgt neu definieren würde:
#define atomic_read(v) (v)->counter
Der Compiler würde eine Diagnose über die Neudefinition ausgeben. Diese Warnung wird ausgegeben, weil ein + 0
vorhanden ist in der Definition atomic_read
von im atomic.h
Datei.
Wenn da nicht die + 0
wäre , hätte der Compiler keine Diagnose ausgegeben.
Ein Minimalbeispiel zur Veranschaulichung dieses Problems:
//atomic.h
#define atomic_read(v) ((v)->counter + 0)
#define atomic64_read(v) ((v)->counter)
//some source file that includes atomic.h
#define atomic_read(v) ((v)->counter) //redefinition error
#define atomic64_read(v) ((v)->counter) //no redefinition error
Siehe Demo
Es verhindert, dass das Ergebnis ein lvalue ist, sodass Sie es nicht fälschlicherweise zuweisen oder seine Adresse übernehmen können.