在linux内核2.6.26中,我发现“ #define atomic_read(v)((v)->计数器+ 0)”,为什么是“ +0”?

时间:2019-04-24 07:33:20

标签: 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)

3 个答案:

答案 0 :(得分:10)

如果未使用+ 0,则可能是您偶然分配的左值,即

if (atomic_read(v) = 42) {
    ...
}

将“工作” ...代替+ 0,您可以只使用一元+,即

(+(v)->counter)

不过,在一般情况下,+ 0+有一个优势:+要求参数必须是算术类型 -但是指针不是算术类型。然而+ 0同样适用于指针(而且对于单独的指针,您可以使用&*将左值转换为表达式的值;这甚至可以保证适用于空指针)

答案 1 :(得分:7)

在重新定义了类似函数的宏+ 0atomic_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 

编译器将发出有关重新定义的诊断。发出此警告的原因是,+ 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

答案 2 :(得分:5)

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