C语言 在 C 中屏蔽和提取位

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26359068/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:27:26  来源:igfitidea点击:

Mask and extract bits in C

cmaskbitwise-operatorsbit-shiftbitwise-and

提问by stillAFanOfTheSimpsons

I've been looking at posts about mask but still can't get my head around how to extract certain bits from a number in C.

我一直在看关于掩码的帖子,但仍然无法理解如何从 C 中的数字中提取某些位。

Say if we have a int number 0001 1010 0100 1011, so it's hex representation is x1a4bright? If I want to know the 5th to 7th number, which is 101in this case, shall I use int mask= 0x0000 1110 0000 0000, int extract = mask&number?

假设我们有一个int number 0001 1010 0100 1011,那么它的十六进制表示是否x1a4b正确?如果我想知道第 5 到第 7 个数字,101在这种情况下,我应该使用int mask= 0x0000 1110 0000 0000, int extract = mask&number?

Also how can I check if it is 101? I guess ==won't work here... Many thanks!

另外我如何检查它是否是101?我想==不会在这里工作...非常感谢!

回答by alk

Assuming the gcc extension 0bto define binary literals:

假设 gcc 扩展0b定义二进制文字:

int number = 0b0001101001001011; /* 0x1a4b */
int mask =   0b0000111000000000; /* 0x0e00 */
/* &'ed:     0b0000101000000000;    0x0a00 */
int extract = mask & number;     /* 0x0a00 */

if (extract == 0b0000101000000000)
/* or if 0b is not available:
if (extract == 0x0a00 ) */
{
  /* success */
}
else
{
  /* failure */
}

回答by PandaConda

Masking is done by setting all the bits except the one(s) you want to 0. So let's say you have a 8 bit variable and you want to check if the 5th bit from the is a 1. Let's say your variable is 00101100. To mask all the other bits we set all the bits except the 5th one to 0 using the & operator:

屏蔽是通过将所有位设置为 0 来完成的。假设您有一个 8 位变量,并且您想检查第 5 位是否为 1。假设您的变量为00101100。为了屏蔽所有其他位,我们使用 & 运算符将除第 5 位以外的所有位设置为 0:

00101100 & 00010000

Now what this does is for every bit except the 5th one, the bit from the byte on the right will be 0, so the result of the & operation will be 0. For the 5th bit, however, the value from the right bit is a 1, so the result will be whatever the value of hte 5th bit from the left byte is - in this case 0:

现在它所做的是对于除第 5 位以外的每一位,右边字节的位将为 0,因此 & 操作的结果将为 0。然而,对于第 5 位,右边位的值是a 1,因此结果将是从左字节起第 5 位的任何值 - 在这种情况下为 0:

Now to check this value you have to compare it with something. To do this, simply compare the result with the byte on the right:

现在要检查这个值,你必须将它与某些东西进行比较。为此,只需将结果与右侧的字节进行比较:

result = (00101100 & 00010000) == 00000000

To generalize this, you can retrieve any bit from the lefthand byte simply by left-shifting 00000001 until you get the bit you want. The following function achieves this:

为了概括这一点,您可以通过左移 00000001 直到获得您想要的位来从左侧字节中检索任何位。以下函数实现了这一点:

int getBit(char byte, int bitNum)
{
    return (byte & (0x1 << (bitNum - 1)))
}

This works on vars of any size, whether it's 8, 16, 32 or 64 (or anything else for that matter).

这适用于任何大小的变量,无论是 8、16、32 还是 64(或其他任何大小)。

回答by sirlark

You need to mask andshift. Either shift the value you are comparing to, or the value you are comparing. I find it easier to think about by shifting the value you are comparing to. So if you're trying to extract the 5th to 7th digits (from the left), you shift right9 positions (16-7) so that the 7th digit is now the rightmost, then apply 0x7 (111 in binary) as a mask to get only the rightmost three binary digits

你需要屏蔽转移。要么改变你正在比较的值,要么改变你正在比较的值。我发现通过改变你正在比较的价值来思考更容易。因此,如果您尝试提取第 5 至第 7 位数字(从左侧),则向右移动9 个位置 (16-7),以便第 7 位数字现在位于最右侧,然后应用 0x7(二进制 111)作为掩码只得到最右边的三个二进制数字

int i = 0x1A4B;
if (((i >> 9) & 0x07) == 0x05) { // 0x05 = 101 in binary
    //do what you need to
}

回答by Baldrickk

First, the digits in binary are (usually) counted from the right (10th and 12th digit) or you say 5th and 7th most significant digits.

首先,二进制中的数字(通常)从右边(第 10 位和第 12 位)开始计数,或者您说第 5 位和第 7位最高有效位

int mask =  0x0E00;  // 0000 1110 0000 0000;
int extract = mask & number;

results in:

结果是:

extract = 0000 1010 0000 0000

You can do

你可以做

if (extract == 0x0A00 /*0000 1010 0000 0000*/){}

to test, or:

测试,或:

if (( extract >> 9 ) == 0x05){}

Both of the statements in the if will return true with your sample number.

if 中的两个语句都将使用您的样本编号返回 true。

Usually with a mask you will find yourself testing a single digit. You could use a function like this to test it:

通常使用面罩,您会发现自己在测试一位数。您可以使用这样的函数来测试它:

bool digit_value( unsigned int number, unsigned int digit)
{
    return (1 << digit) & number;
}

int main()
{
    unsigned int number = 0x1A4B;
    int should_be_three = 0;
    should_be_three +=  digit_value(number, 10);
    should_be_three += !digit_value(number, 11);
    should_be_three +=  digit_value(number, 12);
    printf("%s", (should_be_three == 3?"it worked":"it didn't work"));
    return 0;
}

回答by noktigula

It may be simpler to check bits one-by-one, not all at once. At first, you create mask for interested bit:

逐个检查位可能更简单,而不是一次检查所有位。首先,您为感兴趣的位创建掩码:

int fifthBitMask = 1 << 4;
int fifthBitResult = number & fifthBitMask;

int seventhBitMask = 1 << 6;
int seventhBitResult = number & seventhBitMask;

Now, you can compare results with zero OR with mask. Comparing with zero can be omitted, so you can just use simple if:

现在,您可以将结果与零或与掩码进行比较。可以省略与零的比较,因此您可以使用简单的 if:

if (fifthBitResult && seventhBitResult)
{
    //your code here
}

Also, you can compare with masks. After operation &, in result will set only bits, which was set in mask. So, it could like this: if (fifthBitResult == fifthBitMask && seventhBitResult == seventhBitMask) { // your code here }

此外,您可以与面具进行比较。操作 & 之后,结果将只设置位,这是在掩码中设置的。所以,它可能是这样的: if (fifthBitResult == FifthBitMask && SevenBitResult == FifthBitMask) { // 你的代码在这里 }

So, if result of operation is equals to mask, you can do this with one operation:

因此,如果操作结果等于掩码,您可以通过一个操作来做到这一点:

int mask = 0x5 << 4; // 0x5 is hex representation of 101b
int result = number & mask;
if (result == mask)
{
    // your code here
}

回答by Ruslan Gerasimov

First of all your calculation for bits 7-6-5 is incorrct. You stated it was 101 but it is 010 (for x1a43) Second of all, to get these bits (the value represented by these bits) you should do &0xE0.

首先,您对位 7-6-5 的计算是不正确的。您说它是 101,但它是 010(对于 x1a43) 其次,要获得这些位(这些位表示的值),您应该这样做&0xE0

int my_bits_from_5to7 = number & 0xE0;

int my_bits_from_5to7 = number & 0xE0;

回答by hitesh

shall I use int mask= 0x0000 1110 0000 0000, int extract = mask&number?- Yes you can do this.

我应该使用 int mask= 0x0000 1110 0000 0000, int extract = mask&number?- 是的,你可以这样做。

Also how can I check if it is 101? Sure you can check this- 0000 1010 0000 0000 which is 1280 in int .

另外我如何检查它是否是101?当然你可以检查这个 - 0000 1010 0000 0000 这是 1280 在 int 。

extract== 1280

提取== 1280