简体   繁体   English

了解C编程中的位操作(设置/清除)

[英]Understanding bit manipulation (set/clear) in C programming

I'm stuck understanding bit operations on integers in C. 我一直不了解C中对整数的位操作。

Suppose I have the number 13. Its binary representation is 1101 . 假设我有数字13。其二进制表示形式是1101 How can I set the bit at its second position? 如何将钻头设置在第二位置? How can I clear the bit? 我如何清除位?

Here is the function I wrote so far for setting the bit: 这是我到目前为止编写的用于设置该位的函数:

int setBit(int data, int pos, int val)
{       
    if (val==1)
        data |= (1U << (pos - 1));
    else
        data ^= (1U << (pos-1));

    return data;
}

Will this work correctly? 这样可以正常工作吗?

n = n & (~(1U <<x)) will reset the bit in position x. n = n & (~(1U <<x))将重置位置x的位。 Actually what we are doing suppose n=1101 We want to reset 3rd bit. 实际上,我们在假设n = 1101,我们想重置第3位。

How does it work? 它是如何工作的?

So 1U <<3=000....1000 所以1U << 3 = 000 .... 1000

~( 1U <<3)=111....0111 〜(1U << 3)= 111 .... 0111

n=000..1101 n = 000..1101

& 111..0111 &111..0111

Result is 000..0101. 结果是000..0101。

For inserting a bit y at position x:(position starts from 0) 用于在位置x处插入位y :(位置从0开始)

1101---->11y01 Giving the example for position 2. 1101 ----> 11y01给出位置2的示例。

num= FFFF FFFF (in hex)(all 1's) //1111......1111
number=N  // in which you will insert bit
num1=num<<x;      //for x=2 as in this case
                  //num1=1111.....1100
num2=~(num1);     //num2=0000.....0011
lowbits=N & num2; //    =0000.....0001 (N=1101)
highbits= N &num1;//    =0000.....1100
highbits<<=1;     //    =0000....11000 
N= highbits | lowbits;//=0000....11001

Now set the x-th bit(here x=2) as you required using the method described below 现在,使用以下所述的方法根据需要设置第x个位(此处x = 2)


Note : More generally changing the kth bit of number n to y (maybe 0 or 1) can be done this way 注意 :通常,可以将n的第k位更改为y(也许为0或1)

n^=(-y ^ n) & (1U <<k); (&- logical and)

Deletion of a bit is similar to insertion. 删除一点类似于插入。 Step by step perform the operation and you will get it. 逐步执行操作,您将得到它。

EDIT : I have changed the use of 1 to 1U because in first case when using only 1 without any modifiers is defined to be an signed int. 编辑 :我将1的使用更改为1U,因为在第一种情况下,仅使用1而没有任何修饰符的情况定义为带符号的int。 From K&R the right shifts of signed values are implementation defined. 通过K&R,可以定义实现值的右移。 Also if you left-shift a signed number so that the sign bit is affected, the result is undefined. 同样,如果左移带符号的数字以使符号位受影响,则结果不确定。

These operations on unsigned value have well define behaviour: Vacated fields are filled with zeroes. 这些对无符号值的操作具有良好的定义:空字段填充为零。

Setting, clearing and toggling the state of a bit is straightforward: 设置,清除和切换位状态很简单:

inline void bit_set (unsigned long *bf, unsigned char n) 
{ *bf |= (1 << n); }

inline void bit_clear (unsigned long *bf, unsigned char n) 
{ *bf &= ~(1 << n); }

inline void bit_toggle (unsigned long *bf, unsigned char n) 
{ *bf ^= (1 << n); }

Note: bitfields, and the functions above, are zero based (ie the least significant bit is bit 0 not bit 1 ) So if you want to clear, set or toggle the second bit from the right ( bit index 1 , the 2's bit (binary) , or bit 2 counting right-to-left), you pass a bit index of 1 . 注意:位域和上面的函数都是从零开始的 (即,最低有效位是bit 0而不是bit 1 ),因此,如果要清除,设置或从右边切换第二位( bit index 1 ,即2's bit (binary)或从右到左计数的第bit 2 ),则传递的bit index of 1 n in the functions above is the bit index . 上面函数中的nbit index The following is a quick reference: 以下是快速参考:

           +-----+-----+-----+-----+-----+-----+-----+-----+
bit index  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
           +-----+-----+-----+-----+-----+-----+-----+-----+
binary     | 128 |  64 |  32 |  16 |   8 |   4 |   2 |   1 |
           +-----+-----+-----+-----+-----+-----+-----+-----+

Here is a quick example of the use operating on bit 1 , (the 2's bit in binary): 这是bit 1 (二进制的2的位)上使用的用法的快速示例:

#include <stdio.h>
#include <stdlib.h>

#define WDSZ 64

/* bit functions */
inline void bit_set     (unsigned long *bf, unsigned char n) { *bf |= (1 << n); }
inline void bit_clear   (unsigned long *bf, unsigned char n) { *bf &= ~(1 << n); }
inline void bit_toggle  (unsigned long *bf, unsigned char n) { *bf ^= (1 << n); }

/* simple return of binary string */
char *binstr (unsigned long n);

int main (int argc, char **argv) {

    unsigned long bf = (argc > 1) ? strtoul (argv[1], NULL, 10) : 13;

    printf ("\n original value  : %3lu  (%s)\n", bf, binstr (bf));

    bit_set (&bf, 1);
    printf (" set bit 1       : %3lu  (%s)\n", bf, binstr (bf));

    bit_clear (&bf, 1);
    printf (" clear bit 1     : %3lu  (%s)\n", bf, binstr (bf));

    bit_toggle (&bf, 1);
    printf (" toggle bit 1    : %3lu  (%s)\n\n", bf, binstr (bf));

    return 0;
}

/* simple return of binary string */
char *binstr (unsigned long n) {

    static char s[WDSZ + 1] = {0};
    char *p = s + WDSZ;

    while (n) {
        p--;
        *p = (n & 1) ? '1' : '0';
        n >>= 1;
    }
    return p;
}

Output 输出量

$ ./bin/bitsetcleartoggle

 original value  :  13  (1101)
 set bit 1       :  15  (1111)
 clear bit 1     :  13  (1101)
 toggle bit 1    :  15  (1111)

Here is a simple answer for what I understand your problem to be: 以下是我了解您的问题的简单答案:

int setBit(int data, int pos, int val) {
    if (val)
        return data | (1U << (pos - 1));
    else
        return data & ~(1U << (pos - 1));
}

But I think numbering the bits starting at 1 is not a good idea. 但是我认为对从1开始的位进行编号不是一个好主意。 The more common usage is to number the bits from 0 to sizeof(type) * CHAR_BIT - 1 更常见的用法是将位数从0编号为sizeof(type) * CHAR_BIT - 1

whenever I have a problem like this I will break it down into smaller parts... 每当遇到这样的问题时,我都会将其分解为较小的部分...

suppose i have no 13 binary of 13 is 1101 假设我没有13的13二进制是1101

now how can i add extra bit at second position? 现在如何在第二位置添加额外的位?

ok that is pretty straight forward... first let make a number with a bit in the second position, zero's everywhere else... we will use an int for convenience... 好吧,这很简单...首先让一个数字放在第二个位置,零在其他所有位置...为了方便起见,我们将使用int ...

int mask = 2; // or 0x2 if you rather or 0b10 if your compiler supports that ...

well that isn't very special, I can't reuse that machinery as it were... so let try a different way... 好吧,这不是很特别,我无法像以前那样重复使用该机器...所以让我们尝试另一种方式...

int mask = 1 << 1; // 1 in the fist position moved one to the left...

ok now we have part, now there are 2 intuitive ways to set that on our 13... 好的,现在我们有了一部分,现在有两种直观的方法可以在我们的13个上进行设置...

int answer = 13 | mask; // binary OR

or 要么

int answer = 13 + mask;

these 2 are the same for 13... but will give you different answers for 14... because + always adds the value, and | 这两个对于13是相同的...但是对于14将为您提供不同的答案...因为+总是将值相加,并且| will only change the bits that aren't set on the left side... so you need to pick the semantics that are correct for you... 只会更改左侧未设置的位...所以您需要选择对您来说正确的语义...

now your second question is a little trickier ... first we will pick the same mask... 现在您的第二个问题有些棘手...首先,我们将选择相同的口罩...

//pick nth bit
int mask = 1 < n;
// now to toggle that on a number... XOR
int answer = q ^ mask;

I like using the n'th vs position because it makes more sense in the 0 case... 我喜欢使用第n个vs位置,因为在0情况下它更有意义...

    //For Inserting Bit 

    int insertbit(int data,int pos,int val)
{
    int no1,no2;

    no1=data;

    no1=no1>>(pos-1);

    no1=no1<<(pos-1);

    no2=data-no1;

    no1=no1<<1;

    no1=no1 | no2;

        if(val==1)
      {
           no1=setbit(no1,pos,val);
      }

    return no1;
}

          //Setting Bits



    int setbit(int data,int pos,int val)
{
            int no=1;

           no=no<<(pos-1);

            if(val==0)
        {
            no=~no;
            data=data&no;
        }   
            else
        {
            data=no|data;
        }


        return data;

}

I Coded This Way But I Need Some Shortcut for code insert function 我以这种方式编码,但是我需要一些快捷方式来插入代码

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

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