无符号整数4的一元否定

时间:2013-11-29 21:28:51

标签: c

如果x是unsigned int类型,则这些语句之间存在差异:

return (x & 7);

return (-x & 7);

我理解否定无符号值会给出max_int - value的值。但是,在任何特定的边界条件下,上述两种陈述中的回报值(即真/假)是否存在差异,或者它们在功能上是否相同?

3 个答案:

答案 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 int1 - 已经在你的问题上产生了不同的结果表达。 1u & 71,而-1u & 77。你有什么意思吗?

答案 2 :(得分:1)

如果你专门询问真/假(即零/非零)和两个补码,那么确实没有区别。 (然而,你不仅返回一个简单的真值,而且允许true的不同位模式。只要调用者不区分,那就没问题。)

考虑如何形成二进制补码否定:反转位然后递增。由于您只采用最低有效位,因此增量将不会进位。这是必要的,所以你不能用除了一系列最低有效位之外的任何东西来做这件事。

让我们看看这两种情况:

首先,如果三个低位为零(对于false当量)。反转给出所有的,递增将它们再次变为零。第四个和更重要的位可能不同,但它们不会影响最低有效位,并且它们不会影响结果,因为它们被屏蔽掉了。所以这就行了。

其次,如果三个低位不全为零(对于true当量)。这可以改变为false的唯一方法是当增量操作将它们保持为零时,这种情况只有在它们之前全部为1时才会发生,而这反过来只有在它们在反转之前全部为零时才会发生。这不可能,因为这是第一种情况。同样,更高有效位不影响三个低位,它们被屏蔽掉。所以结果不会改变。

但同样,这仅在调用者仅考虑真值(所有位为零/不是所有位为零)时以及当掩码允许从最低有效位开始而没有间隙的位范围时才有效。