我在linux-2.6.26(linux-2.6.26 / include / asm-alpha / atomic.h)中找到了这个,并且在这里不知道为什么+0。
#define atomic_read(v) ((v)->counter + 0)
#define atomic64_read(v) ((v)->counter + 0)
如果重新定义了类似函数的宏+ 0
和atomic_read
,可能会为编译器添加atomic64_read
以发出诊断信息。
根据C标准,如果第二个定义是具有相同数量和参数拼写的类似函数的宏,并且两个替换列表相同,则可以重新定义标识符,该标识符是类似函数的宏。
从C11标准(n1570),部分6.10.3/2:
...同样,当前定义为类似函数宏的标识符不应由另一个
#define
预处理指令重新定义,除非第二个定义是具有相同数字和参数拼写的类函数宏定义,以及两个替换列表是相同的。
内核版本(2.6.26)相当陈旧,但在C89标准之前的旧标准中可以找到类似的重新定义禁令。
目前,宏atomic_read
和atomic64_read
在文件atomic.h
中定义。
如果用户将在某个源文件中重新定义它们,如下所示:
#define atomic_read(v) (v)->counter
编译器将发出有关重新定义的诊断信息。发出此警告是因为+ 0
文件中定义atomic_read
中有atomic.h
。
如果不是+ 0
,编译器就不会发出诊断信息。
演示此问题的最小示例:
//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
见Demo
如果没有使用+ 0
,那么你可以偶然分配一个左值,即
if (atomic_read(v) = 42) {
...
}
将“工作”...而不是+ 0
你可以只使用一元+
,即
(+(v)->counter)
然而,+ 0
在通用情况下比+
有一个很好的优势:+
要求参数是算术类型 - 但指针不是算术类型。然而+ 0
可以用于指针(并且仅针对指针,你可以使用&*
将左值转换为表达式的值;这保证适用于偶数空指针)
它可以防止结果成为左值,因此您不能错误地为其分配或获取其地址。