Si + 0
no se usa, sería un valor l que podría asignar por accidente, es decir,
if (atomic_read(v) = 42) {
...
}
"funcionaría"... En lugar de + 0
podrías usar unario +
, es decir,
(+(v)->counter)
Sin embargo + 0
tiene uno buena ventaja sobre +
en caso genérico:+
requiere que el argumento sea un tipo aritmético - pero los punteros no son de tipo aritmético. Sin embargo, + 0
funcionaría para punteros por igual (y solo para punteros, puede usar &*
para convertir lvalue en un valor de expresión; esto está garantizado para funcionar incluso con punteros nulos)
Es posible que el + 0
se agregó para que el compilador emita un diagnóstico en caso de que haya una redefinición de las macros similares a funciones atomic_read
y atomic64_read
.
Según el estándar C, es posible redefinir un identificador que es una macro similar a una función si la segunda definición también es una macro similar a una función que tiene el mismo número y ortografía de parámetros, y las dos listas de reemplazo son idénticas.
Del estándar C11 (n1570), sección 6.10.3/2:
... Del mismo modo, un identificador actualmente definido como una macro similar a una función no será redefinido por otro #define
directiva de preprocesamiento a menos que la segunda definición sea una definición de macro similar a una función que tenga el mismo número y ortografía de parámetros, y las dos listas de reemplazo sean idénticas.
La versión del kernel (2.6.26) es bastante antigua, pero se puede encontrar una prohibición similar sobre dicha redefinición en estándares más antiguos hasta el estándar C89.
Actualmente las macros atomic_read
y atomic64_read
se definen en el archivo atomic.h
.
Si el usuario los redefiniera en algún archivo fuente como se muestra a continuación:
#define atomic_read(v) (v)->counter
El compilador emitiría un diagnóstico sobre la redefinición. Esta advertencia se emite porque hay un + 0
en la definición atomic_read
de en el atomic.h
expediente.
Si no fuera por el + 0
, el compilador no habría emitido un diagnóstico.
Un ejemplo mínimo para demostrar este 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
Ver demostración
Evita que el resultado sea un valor l, por lo que no puede asignarlo incorrectamente ni tomar su dirección.