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

问题描述 投票:9回答:3

我在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)
c linux
3个回答
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


10
投票

如果没有使用+ 0,那么你可以偶然分配一个左值,即

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

将“工作”...而不是+ 0你可以只使用一元+,即

(+(v)->counter)

然而,+ 0在通用情况下比+有一个很好的优势:+要求参数是算术类型 - 但指针不是算术类型。然而+ 0可以用于指针(并且仅针对指针,你可以使用&*将左值转换为表达式的值;这保证适用于偶数空指针)


5
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.