Se + 0
non viene utilizzato, sarebbe un lvalue che potresti assegnare per sbaglio, ad esempio
if (atomic_read(v) = 42) {
...
}
"funzionerebbe"... Invece di + 0
potresti semplicemente usare unario +
, ovvero
(+(v)->counter)
Comunque + 0
ne ha uno buon vantaggio su +
in caso generico:+
richiede che l'argomento sia un tipo aritmetico - ma i puntatori non sono di tipo aritmetico. Ancora + 0
funzionerebbe allo stesso modo per i puntatori (e solo per i puntatori, puoi usare &*
per convertire lvalue in un valore di espressione; questo è garantito per funzionare anche con puntatori nulli)
È possibile che il file + 0
è stato aggiunto per consentire al compilatore di emettere una diagnostica nel caso ci fosse una ridefinizione delle macro simili a funzioni atomic_read
e atomic64_read
.
Secondo lo standard C è possibile ridefinire un identificatore che è una macro simile a una funzione se la seconda definizione è anch'essa una macro simile a una funzione che ha lo stesso numero e ortografia dei parametri e le due liste di sostituzione sono identiche.
Dallo standard C11 (n1570), sezione 6.10.3/2:
... Allo stesso modo, un identificatore attualmente definito come macro simile a una funzione non deve essere ridefinito da un altro
#define
direttiva di preelaborazione a meno che la seconda definizione non sia una definizione di macro simile a una funzione che abbia lo stesso numero e ortografia dei parametri e i due elenchi di sostituzione siano identici.
La versione del kernel (2.6.26) è piuttosto vecchia ma un divieto simile a tale ridefinizione può essere trovato negli standard precedenti fino allo standard C89.
Attualmente le macro atomic_read
e atomic64_read
sono definiti nel file atomic.h
.
Se l'utente li ridefinisse in qualche file sorgente come di seguito:
#define atomic_read(v) (v)->counter
Il compilatore emetterebbe una diagnostica sulla ridefinizione. Questo avviso viene emesso perché è presente un + 0
nella definizione atomic_read
di nel atomic.h
file.
Se non fosse per il + 0
, il compilatore non avrebbe emesso una diagnostica.
Un esempio minimo per dimostrare questo problema:
//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
Guarda la demo
Impedisce che il risultato sia un lvalue, quindi non puoi assegnarlo erroneamente o prenderne l'indirizzo.