Pokud + 0
se nepoužívá, byla by to hodnota, kterou byste mohli přiřadit náhodou, tj.
if (atomic_read(v) = 42) {
...
}
by "fungovalo"... Místo + 0
stačí použít unární +
, tj.
(+(v)->counter)
Nicméně + 0
má jeden dobrá výhoda oproti +
v obecném případě:+
vyžaduje, aby argument byl aritmetického typu - ale ukazatele nejsou aritmetického typu. Přesto + 0
by fungovalo pro ukazatele podobně (a pro ukazatele samotné můžete použít &*
převést lvalue na hodnotu výrazu; zaručeně to bude fungovat i pro nulové ukazatele)
Je možné, že + 0
bylo přidáno, aby kompilátor vydal diagnostiku v případě, že došlo k předefinování maker podobných funkcím atomic_read
a atomic64_read
.
Podle standardu C je možné předefinovat identifikátor, který je makrem podobným funkci, pokud je druhá definice také makro podobné funkci, které má stejný počet a pravopis parametrů a oba seznamy náhrad jsou totožné.
Ze standardu C11 (n1570), sekce 6.10.3/2:
... Stejně tak identifikátor aktuálně definovaný jako funkční makro nesmí být předefinován jiným
#define
direktiva předběžného zpracování, pokud druhá definice není definicí makra podobnou funkci, která má stejný počet a pravopis parametrů a dva seznamy náhrad jsou totožné.
Verze jádra (2.6.26) je poměrně stará, ale podobný zákaz takového předefinování lze nalézt ve starších standardech až po standard C89.
Aktuálně jsou makra atomic_read
a atomic64_read
jsou definovány v souboru atomic.h
.
Pokud by je uživatel předefinoval v nějakém zdrojovém souboru, jak je uvedeno níže:
#define atomic_read(v) (v)->counter
Kompilátor vydá diagnostiku o nové definici. Toto varování bylo vydáno, protože existuje + 0
v definici atomic_read
z v atomic.h
soubor.
Kdyby nebylo + 0
, kompilátor by nevydal diagnostiku.
Minimální příklad pro demonstraci tohoto problému:
//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
Viz Demo
Zabraňuje tomu, aby výsledek byl lvalue, takže k němu nemůžete chybně přiřadit nebo převzít jeho adresu.