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

时间:2015-03-21 17:20:47

标签: c bit-manipulation bit

我无法理解C中对整数的位操作。

假设我有数字13.它的二进制表示是1101。如何将钻头设置在第二个位置?我怎么能清除这个位?

这是我到目前为止写的用于设置位的函数:

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

    return data;
}

这会正常工作吗?

5 个答案:

答案 0 :(得分:2)

n = n & (~(1U <<x))将重置位置x的位。 实际上我们在做什么假设n = 1101 我们想重置第3位。

它是如何工作的?

所以1U&lt;&lt; 3 = 000 .... 1000

〜(1U <&lt; 3)= 111 .... 0111

n = 000..1101

&安培; 111..0111

结果是000..0101。

用于在位置x处插入位y :(位置从0开始)

1101 ----&GT; 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

现在使用下面描述的方法设置第x位(此处为x = 2)


注意:更一般地,将数字n的第k位改为y(可能是0或1)可以这样做

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

删除一点类似于插入。一步一步地执行操作,你就可以得到它。

编辑:我已经改变了1到1U的使用,因为在第一种情况下,只使用1而没有任何修饰符被定义为带符号的int。从K&amp; R,签名值的右移是实现定义的。此外,如果左移有符号数字以使符号位受影响,则结果是未定义的。

  

对无符号值的这些操作很好地定义了行为:空位字段用零填充。

答案 1 :(得分:1)

设置,清除和切换位状态非常简单:

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); }

注意:位域和上面的函数基于零(即最低有效位是bit 0而不是bit 1)所以如果要从右侧(bit index 12's bit (binary)bit 2从右向左计数)清除,设置或切换第二位,您传递bit index of 1 。上述函数中的nbit index。以下是快速参考:

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

以下是在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;
}

<强>输出

$ ./bin/bitsetcleartoggle

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

答案 2 :(得分:1)

以下是我理解您的问题的简单答案:

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

但我认为从1开始编号是不是一个好主意。更常见的用法是将0sizeof(type) * CHAR_BIT - 1

的位数进行编号

答案 3 :(得分:0)

每当我遇到这样的问题时,我都会把它分解成更小的部分......

  

假设我没有13的二进制13是1101

     

现在如何在第二个位置添加额外的位?

好的,这是非常简单的...首先让我们在第二个位置做一个数字,零在其他地方...我们将使用int以方便...

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

那不是很特别,我不能重复使用那台机器......所以让我们尝试不同的方式......

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

好了,现在我们有了一部分,现在有两种直观的方式来设置我们的13 ...

int answer = 13 | mask; // binary OR

int answer = 13 + mask;

这两个是相同的13 ...但会给你不同的答案14 ...因为+总是添加值,而|只会改变不是设置在左侧...所以你需要选择适合你的语义......

现在你的第二个问题有点棘手......首先我们会选择相同的面具......

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

我喜欢使用第n个vs位置,因为它在0的情况下更有意义......

答案 4 :(得分: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;

}

我以这种方式编码,但我需要一些代码插入功能的快捷方式