GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Im Linux-Kernel 2.6.26 fand ich #define atomic_read(v) ((v)->counter + 0), warum +0?

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.


Linux
  1. Linux – Kernel-IP-Weiterleitung?

  2. Linux – Ein verdorbener Kernel in Linux?

  3. Linux – Warum gibt es eine Linux-Kernel-Richtlinie, um den Benutzerbereich niemals zu unterbrechen?

  4. Warum gibt pr_debug des Linux-Kernels keine Ausgabe aus?

  5. Warum den Linux-Kernel vor dem Root-Benutzer schützen?

Dmesg-Befehl unter Linux

Sysctl-Befehl unter Linux

Ist Linux ein Betriebssystem oder ein Kernel?

Linux-Kernel vs. Mac-Kernel

Warum müssen Systemaufruftabellen in Linux geändert werden?

Warum sollte jemand UserMode Linux (UML) ausführen wollen?