简体   繁体   English

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

[英]Minus operator used as unary bitwise operation

I don't fully understand how the "-" operator affects the following code: 我不完全理解“ - ”运算符如何影响以下代码:

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

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

Could someone explain what COMP(a) and COMP(b) are and how they are calculated? 有人可以解释COMP(a)和COMP(b)是什么以及如何计算它们?

(x) & -(x) is equal to the lowest bit set in x when using 2's complement for representing binary numbers. (x) & -(x)等于使用2的补码表示二进制数时在x设置的最低位。

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

the "-" sign negative the value of the short parameter in a two's complement way. “ - ”符号以二进制补码的方式将短参数的值否定。 (in short, turn all 0 to 1, 1 to 0 and then add 1) (简而言之,将全0转为1,将1转为0然后再加1)

so 0xA55A in binary is 1010 0101 0101 1010 所以二进制的0xA55A是1010 0101 0101 1010
then -(0xA55A) in binary is 0101 1010 1010 0110 然后 - 二进制的(0xA55A)是0101 1010 1010 0110
run & between them will give you 0000 0000 0000 0010 运行&他们之间将会给你0000 0000 0000 0010

-(x) negates x . -(x)否定x Negation in two's complement is the same as ~x+1 (bitflip+1) as the code below shows: 二进制补码中的否定与~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)

}

When you bitand a value with its bitfliped value, you get 0. When you bitand a value with its bitfliped value + 1 (=its negated value) you get the first nonzero bit from the right. 当你使用bitfliped值对某个值进行bit和bit时,得到0.当你使用bitfliped值+ 1(=其否定值)对某个值进行位操作时,你会得到右边的第一个非零位。

Why? 为什么? If the rightmost bit of ~x is 1, adding 1 to it will yield 0 with carry=1 . 如果~x的最右边的位是1,则向其添加1将产生0其中carry=1 You repeat this while the rightmost bits are 1 and, zeroing those bits. 在最右边的位为1时重复此操作,并将这些位置零。 Once you hit zero (which would be 1 in x , since you're adding 1 to ~x ), it gets turned into 1 with carry==0, so the addition ends. 一旦你达到零(在x1 ,因为你将1加到~x ),它会随着carry == 0变成1,所以加法结束。 To the right you have zeros, to the left you have bitflips. 在右边你有零,在左边你有点翻转。 You bitand this with the original and you get the first nonzero bit from the right. 你和原版一起咬了这个,你从右边得到第一个非零位。

Basically, what COMP does is AND the two operands of which one is in its original form and one of which is a negation of it's form. 基本上,COMP所做的是AND两个操作数,其中一个是原始形式,其中一个是对它形式的否定。

How CPUs typically handle signed numbers is using 2's Complement , 2's complement splits the range of a numeric data type to 2, of which (2^n-1) -1 is positive and (2^n-1) is negative. CPU通常如何处理带符号的数字是使用2的补码 ,2的补码将数值数据类型的范围拆分为2,其中(2 ^ n-1)-1为正,(2 ^ n-1)为负。

The MSB (right-most bit) represents the sign of the numeric data MSB(最右边的位)表示数字数据的符号

eg 例如

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

So what COMP does by doing an AND on positive and negative version of the numeric data is to get the LSB (Left-most bit) of the first 1. 因此COMP通过对数字数据的正负版本执行AND来获得第一个1的LSB(最左边的位)。

I wrote some sample code that can help you understand here: http://coliru.stacked-crooked.com/a/935c3452b31ba76c 我写了一些示例代码,可以帮助您理解: http//coliru.stacked-crooked.com/a/935c3452b31ba76c

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM