在Linux内核2.6.26中,我找到了“ #define atomic_read(v)((v)-> counter + 0)”,为什么是“ +0”?

Sma*_*Lin 9 c linux

我在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)
Run Code Online (Sandbox Code Playgroud)

Ant*_*ala 10

如果+ 0不使用,它将是您可能偶然分配的左值,即

if (atomic_read(v) = 42) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

会“工作” ...代替+ 0您可以只使用unary +,即

(+(v)->counter)
Run Code Online (Sandbox Code Playgroud)

但是,与一般情况相比,+ 0一个很好的优点++要求参数为算术类型 -但是指针不是算术类型。但是+ 0同样适用于指针(并且仅适用于指针,您可以使用&*将左值转换为表达式的值;这甚至可以保证适用于空指针)


P.W*_*P.W 7

如果+ 0重新定义了类似函数的宏atomic_read和,则可能会添加,以便编译器发出诊断信息atomic64_read

根据C标准,如果第二个定义是同样具有函数编号和参数拼写且两个替换列表相同的类似函数的宏,则可以重新定义标识符,该标识符是类似于函数的宏。

根据C11标准(n1570),第6.10.3 / 2节:

...同样,当前定义为类函数宏的标识符不应由另一个#define预处理指令重新定义,除非第二个定义是具有相同编号和参数拼写的类函数宏定义,并且两个替换列表是相同。

内核版本(2.6.26)相当老,但是在直到C89标准的较早标准中也存在类似的禁止重新定义的规定。

当前,宏atomic_readatomic64_read在文件中定义atomic.h

如果用户要在某些源文件中重新定义它们,如下所示:

#define atomic_read(v)      (v)->counter 
Run Code Online (Sandbox Code Playgroud)

编译器将发出有关重新定义的诊断。发出这个警告,因为有一个+ 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 
Run Code Online (Sandbox Code Playgroud)

观看演示


R..*_*R.. 5

它可以防止结果成为左值,因此您不能错误地为其赋值或获取其地址。