【问题标题】:how can I copy 2 bits from one int to another?如何将 2 位从一个 int 复制到另一个?
【发布时间】:2014-03-21 17:32:40
【问题描述】:

我有两个无符号整数:ab(b 是无符号整数指针)。我想将a 的第 8 位和第 9 位复制到 b 的第 2 位和第 3 位(所有索引都基于 0)。

这就是我的做法:

 bool secondBit =  (a & (1 << 8) ) ;
 bool thirdBit =   (a & (1 << 9) ) ;

 if (secondBit) {
     *b |= (1u << 2);
 }
 if (thirdBit) {
     *b |= (1u << 3);

提醒:b 是一个无符号整数指针。

有没有更好的方法?

【问题讨论】:

  • 对于这样的问题,字节序是否重要?
  • a 不是指针,只是一个 int
  • 请注意,如果它已经在*b 中设置,这实际上并不会重置该位。如果这是您的意图,那么我认为您的代码比最佳答案更清晰。

标签: c++ c bit-manipulation


【解决方案1】:

清除*b的相关位,并将它们设置为a中你想要的位:

*b = (*b & ~0xC) | ((a & 0x300) >> 6);

// This is the 'not' of 00001100, in other words, 11110011
~0xC;

// This zeros the bits of *b that you do not want (b being a pointer)
*b & ~0xC;   // *b & 11110011

//This clears all of a except the bits that you want
a & 0x300;

// Shift the result into the location that you want to set in *b (bits 2 and 3)   
((a & 0x300) >> 6);

// Now set the bits into *b without changing any other bits in *b
*b = (*b & ~0xC) | ((a & 0x300) >> 6);

【讨论】:

  • 我正试图围绕你所写的内容。你能解释一下,我们在这里做什么?
  • @brainydexter (1) 0xC12,二进制表示为...0 1100,按位取反~...1 0011。 And'ing *b 给你一个*b,它的第 2 位和第 3 位被清除。 (2) 0x3000x100 + 0x200,是 2 的 8 次方和 9 次方,表示它们代表第 8 位和第 9 位。 And'ing a 给你一个 a 只有第 8 位和第 9 位。向右移动 6 位,使这些位位于第 2 位和第 3 位。 (3) 对这两个结果进行或运算得到您想要的结果,因此我们将其分配(或他分配)给*b
  • 有道理。感谢@ThoAppelsin 的详细解释!
  • @brainydexter 没问题,兄弟...但是上帝,当我看到这样陈旧的直接答案时,我讨厌它,获得如此多的赞成票...
  • +1,但我会先移动 a,然后应用掩码 (*b = (*b &amp; ~0xC) | ((a &gt;&gt; 6) &amp; 0xC)),因为您在 OR 的两侧都有相同的掩码(以反转为模)。
【解决方案2】:

取决于你对“更好”的定义:)

但是,C++ 中有 std::bitset 类。也许它通过提供一个不易出错的界面来满足您的需求。

【讨论】:

  • 我不知道 std::bitset 的实现,但它的效率可能不如“掩码、移位、取消掩码”方法。
  • 或者更高效。我不知道,我没有测量过 :) 很有可能他的实际应用中的实际差异太小而无法测量。真的很难说没有任何上下文。
【解决方案3】:

这里有一个更详细的方法来创建您正在寻找的结果和代码来测试操作。

#include <stdio.h>

void printBits(int n)
{
   int i = 31;
   char bits[32];
   for ( ; i >= 0; --i, n /= 2 )
   {
      bits[i]= n % 2;
   }

   for ( i = 0; i < 32; ++i )
   {
      printf("%d", bits[i]);
      if ( (i+1)%8 == 0 )
      {
         putchar(' ');
      }
   }
}

int foo(int n1, int n2)
{
   // copy 8th and 9th bit of n1 to 2nd and 3rd bit of n2 
   // (all indices are 0 based).

   // Extract the 8th and 9th bits of n1
   int k1 = 0x00000300;
   int r1 = n1 & k1;

   // Clear the 2nd and 3rd bits of n2.
   int k2 = 0xFFFFFFF9;
   int r2 = n2 & k2;

   // Move the 8th and 9th bits of n1 by 6 to the right
   // to put them in 2nd and 3rd places.
   // Construct the result and return.
   return (r1 >> 6) | r2;
}

int main(int argc, char** argv)
{
   int n1 = atoi(argv[1]);
   int n2 = atoi(argv[2]);

   printf("Input n1: ");
   printBits(n1);
   printf("\n");

   printf("Input n2: ");
   printBits(n2);
   printf("\n");

   int n3 = foo(n1, n2);

   printf("Result  : ");
   printBits(n3);
   printf("\n");
}

样本输出:

./test-19 251282 85 输入n1:00000000 00000011 11010101 10010010 输入n2:00000000 00000000 00000000 10000000 结果:00000000 00000000 00000000 10000100

【讨论】:

    【解决方案4】:

    在给定的代码中,它不会复制位 - 它只是对它们进行排序。它应该这样做

    *b &= ~0xC0;
    

    首先?那么

    *b |= ((a >> 6) & 0xC0);
    

    【讨论】:

    • 这是不正确的。第一行会将*b 除了 bit-0 和bit-1 的所有位归零。您的意思是与 ~0xC 仅将位 2 和位 3 归零。一般来说,在掩码下插入是dst = (dst &amp; ~mask) | (src &amp; mask),其中src的位已经在正确的位置,mask对于我们希望插入的每一位都有一个1,对于我们希望插入的每一位都有一个0希望保留。
    猜你喜欢
    • 1970-01-01
    • 2013-05-02
    • 2014-11-25
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2015-05-18
    相关资源
    最近更新 更多