Si + 0
n'est pas utilisé, il s'agirait d'une lvalue que vous pourriez affecter par accident, c'est-à-dire
if (atomic_read(v) = 42) {
...
}
"fonctionnerait"... Au lieu de + 0
vous pouvez simplement utiliser unaire +
, c'est-à-dire
(+(v)->counter)
Cependant + 0
en a un bon avantage sur +
en cas générique :+
nécessite que l'argument soit un type arithmétique - mais les pointeurs ne sont pas de type arithmétique. Pourtant + 0
fonctionnerait de la même manière pour les pointeurs (et pour les pointeurs seuls, vous pouvez utiliser &*
pour convertir lvalue en une valeur d'expression ; ceci est garanti pour fonctionner même pour les pointeurs nuls)
Il est possible que le + 0
a été ajouté pour que le compilateur émette un diagnostic en cas de redéfinition des macros de type fonction atomic_read
et atomic64_read
.
Selon la norme C, il est possible de redéfinir un identifiant qui est une macro de type fonction si la deuxième définition est également une macro de type fonction qui a le même nombre et la même orthographe de paramètres, et les deux listes de remplacement sont identiques.
De la norme C11 (n1570), section 6.10.3/2 :
... De même, un identifiant actuellement défini comme une macro de type fonction ne doit pas être redéfini par un autre
#define
directive de prétraitement sauf si la deuxième définition est une définition de macro de type fonction qui a le même nombre et la même orthographe de paramètres, et les deux listes de remplacement sont identiques.
La version du noyau (2.6.26) est assez ancienne, mais une interdiction similaire d'une telle redéfinition peut être trouvée dans les normes plus anciennes jusqu'à la norme C89.
Actuellement les macros atomic_read
et atomic64_read
sont définis dans le fichier atomic.h
.
Si l'utilisateur les redéfinissait dans un fichier source comme ci-dessous :
#define atomic_read(v) (v)->counter
Le compilateur émettrait un diagnostic sur la redéfinition. Cet avertissement est émis car il y a un + 0
dans la définition atomic_read
dans le atomic.h
dossier.
S'il n'y avait pas le + 0
, le compilateur n'aurait pas émis de diagnostic.
Un exemple minimal pour illustrer ce problème :
//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
Voir la démo
Cela empêche le résultat d'être une lvalue, vous ne pouvez donc pas lui attribuer ou prendre son adresse par erreur.