[OS] 区分按位与()和逻辑与()
if(vma->flags & MAP_SHARED) {
filewrite(vma->f, addr, len);
}
在这里,if(vma->flags & MAP_SHARED)
使用的是按位与(&
)操作,而不是逻辑与(&&
),原因在于:
1. 区分按位与(&
)和逻辑与(&&
)
-
按位与(
&
):- 用于位操作,检查特定位是否被设置。
- 在这种情况下,
vma->flags
是一个包含多个标志的整数,通过&
可以检查特定位(如MAP_SHARED
)是否为1
。 - 如果
MAP_SHARED
位被设置,条件为true
。
-
逻辑与(
&&
):- 用于逻辑表达式的短路求值。
- 检查两个完整的布尔表达式是否都为
true
。
2. 为什么这里用 &
?
vma->flags
是一个整数,表示多个标志的组合。我们只关心其中的 MAP_SHARED
位是否被设置,而不是整个 flags
的值是否等于某个布尔值。
示例:
假设 vma->flags
值为二进制 0101
,它的含义可能是:
- 第 0 位:
MAP_READ
- 第 1 位:
MAP_WRITE
- 第 2 位:
MAP_SHARED
如果我们想检查 MAP_SHARED
是否被设置:
- 按位与(
&
):vma->flags & MAP_SHARED
- 仅检查第 2 位是否为
1
,而不关心其他位的值。
- 仅检查第 2 位是否为
- 逻辑与(
&&
):vma->flags && MAP_SHARED
- 这会首先将
vma->flags
和MAP_SHARED
分别作为布尔值进行判断,然后再检查它们是否都为true
。这是不符合意图的。
- 这会首先将
3. 使用逻辑与(&&
)的错误后果
如果改成 if(vma->flags && MAP_SHARED)
,逻辑会变成:
vma->flags
是否非零(即存在任意标志)。MAP_SHARED
是否非零(常量通常非零)。
两者都为 true
时,条件才成立。这种逻辑显然不符合我们希望仅检查 MAP_SHARED
位是否被设置的意图。
4. 为什么单独用 &
就足够了?
vma->flags & MAP_SHARED
的结果:
- 如果
MAP_SHARED
位被设置,结果为非零(即true
)。 - 如果
MAP_SHARED
位未被设置,结果为零(即false
)。
这与 if
的语义完全一致,无需额外转换。
总结
使用 &
是因为我们只需要检查 MAP_SHARED
位是否被设置,而不是检查整个表达式是否为布尔意义上的 true
。逻辑与(&&
)不适用于位操作,且会导致错误的逻辑行为。