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
#definedirettiva 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.