减号运算符用作一元按位运算

时间:2019-02-03 13:00:55

标签: c

我不完全了解“-”运算符如何影响以下代码:

#define COMP(x) ((x) & -(x))

unsigned short a = 0xA55A;
unsigned short b = 0x0400;

有人可以解释一下COMP(a)和COMP(b)以及它们的计算方式吗?

4 个答案:

答案 0 :(得分:6)

(x) & -(x)等于使用2的补数表示二进制数时在x中设置的最低位。

这意味着COMP(a) == 0x0002;COMP(b) == 0x0400;

答案 1 :(得分:4)

“-”号以two's complement的方式使short参数的值负。 (简而言之,将所有0变成1,从1变成0,然后再加1)

所以二进制的0xA55A是1010 0101 0101 1010
那么-(0xA55A)二进制为0101 1010 1010 0110
在它们之间运行&会给您0000 0000 0000 0010

答案 2 :(得分:0)

-(x)取反x。二进制补码的负数与~x+1(bitflip + 1)相同 如下代码所示:

#include <stdio.h>
#include <stdio.h>
#include <stdint.h>
int prbits(uintmax_t X, int N /*how many bits to print (from the low end)*/)
{
    int n=0;
    uintmax_t shift=(uintmax_t)1<<(N-1);
    for(;shift;n++,shift>>=1) putchar( (X&shift)?'1':'0');
    return n;
}
int main()
{
    prbits(0xA55A,16),puts("");
    //1010010101011010

    prbits(~0xA55A,16),puts("");
    //0101101010100101

    prbits(~0xA55A+1,16),puts("");
    //0101101010100110
    prbits(-0xA55A,16),puts("");
    //0101101010100110 (same)

}

用位翻转的值对值进行位取值时,得到0。用位翻转的值+ 1(取其负值)值取值时,从右边得到第一个非零位。

为什么?如果~x的最右位为1,则向其加1将产生0carry=1。您在最右边的位为1并将这些位清零时重复此操作。一旦您达到零(在1中将为x,因为您要向~x加1),它将变为1,进位== 0,因此加法结束。右边有零,左边有位翻转。您将其与原始位进行咬合,然后从右侧获得第一个非零位。

答案 3 :(得分:0)

基本上,COMP的作用是AND,两个操作数是其原始形式,而其中一个是其形式的否定。

CPU通常如何使用2's Complement处理带符号的数字,2的补码将数字数据类型的范围拆分为2,其中(2 ^ n-1)-1为正,(2 ^ n-1 )为负。

MSB(最右边的位)代表数字数据的符号

例如

0111 -> +7
0110 -> +6
0000 -> +0
1111 -> -1
1110 -> -2
1100 -> -6

因此,COMP通过对数字数据的正负版本进行“与”运算来获得第一个1的LSB(最左位)。

我写了一些示例代码,可以帮助您在这里理解: http://coliru.stacked-crooked.com/a/935c3452b31ba76c