如果x是unsigned int类型,则这些语句之间存在差异:
return (x & 7);
和
return (-x & 7);
我理解否定无符号值会给出max_int - value
的值。但是,在任何特定的边界条件下,上述两种陈述中的回报值(即真/假)是否存在差异,或者它们在功能上是否相同?
答案 0 :(得分:4)
测试代码:
#include <stdio.h>
static unsigned neg7(unsigned x) { return -x & 7; }
static unsigned pos7(unsigned x) { return +x & 7; }
int main(void)
{
for (unsigned i = 0; i < 8; i++)
printf("%u: pos %u; neg %u\n", i, pos7(i), neg7(i));
return 0;
}
测试结果:
0: pos 0; neg 0
1: pos 1; neg 7
2: pos 2; neg 6
3: pos 3; neg 5
4: pos 4; neg 4
5: pos 5; neg 3
6: pos 6; neg 2
7: pos 7; neg 1
对于4(和0)的具体情况,没有区别;对于其他价值观,存在差异。您可以扩展输入范围,但输出将产生相同的模式。
答案 1 :(得分:1)
首先,否定unsigned int
值会产生UINT_MAX - original_value + 1
。 (例如,0
仍为0
否定。描述否定的另一种方法是对所有位进行完全反转,然后再进行增量。
目前尚不清楚为什么你甚至会问这个问题,因为很明显基本上第一个想到的例子 - unsigned int
值1
- 已经在你的问题上产生了不同的结果表达。 1u & 7
为1
,而-1u & 7
为7
。你有什么意思吗?
答案 2 :(得分:1)
如果你专门询问真/假(即零/非零)和两个补码,那么确实没有区别。 (然而,你不仅返回一个简单的真值,而且允许true
的不同位模式。只要调用者不区分,那就没问题。)
考虑如何形成二进制补码否定:反转位然后递增。由于您只采用最低有效位,因此增量将不会进位。这是必要的,所以你不能用除了一系列最低有效位之外的任何东西来做这件事。
让我们看看这两种情况:
首先,如果三个低位为零(对于false
当量)。反转给出所有的,递增将它们再次变为零。第四个和更重要的位可能不同,但它们不会影响最低有效位,并且它们不会影响结果,因为它们被屏蔽掉了。所以这就行了。
其次,如果三个低位不全为零(对于true
当量)。这可以改变为false
的唯一方法是当增量操作将它们保持为零时,这种情况只有在它们之前全部为1时才会发生,而这反过来只有在它们在反转之前全部为零时才会发生。这不可能,因为这是第一种情况。同样,更高有效位不影响三个低位,它们被屏蔽掉。所以结果不会改变。
但同样,这仅在调用者仅考虑真值(所有位为零/不是所有位为零)时以及当掩码允许从最低有效位开始而没有间隙的位范围时才有效。