【问题标题】:bit swapping with char type in C在 C 中与 char 类型进行位交换
【发布时间】:2010-10-12 18:01:58
【问题描述】:

数据类型为char,模式如下:

源字节:[0][1][2][3][4][5][6][7]

目的地:[6][7][4][5][2][3][0][1]

例如,如果我将 char, 29 传递给此函数,它将执行交换并返回 char 类型的值,即 116。

如何进行交换?

谢谢。

==========================

只是想知道我是否可以这样做?

unsigned char mask = 128;
char num = 0, value1 = 29;
int i, a;

for(i = 0; i < 8; i++) {
  if (i == 0 || i == 1 || i == 6 || i == 7)
    a = 6;
  else
    a = 2;

  if(i < 4)
    num = ((value1 & mask) >> a);
  else
    num = ((value1 & mask) << a);

  result = (result | num);

  if(i<7)
    mask = mask >> 1;
}

【问题讨论】:

  • 嗯?你有一个旋转的 3 位值?但是在一个字符中? 8位?三不干净地分成八..
  • 什么?他的例子是29 = 00011101,他通过重新排列位将其转换为116 = 01110100
  • 这是为了在进行就地 FFT/DFT 后更正地址吗?似曾相识……
  • 噢……我以为他在做一个以 8 为底的操作,而不是一个字节的位旋转。

标签: c char bit-manipulation swap


【解决方案1】:

我通常以另一种方式编号我的位 - 所以位 0 是 LSB。遵循您的编号方案:

unsigned char src = 29;
unsigned char dst = 0;
dst = (((src & 0x80) >> 6) | // bit 0
       ((src & 0x40) >> 6) | // bit 1
       ((src & 0x20) >> 2) | // bit 2
       ((src & 0x10) >> 2) | // bit 3
       ((src & 0x08) << 2) | // bit 4
       ((src & 0x04) << 2) | // bit 5
       ((src & 0x02) << 6) | // bit 6
       ((src & 0x01) << 6) // bit 7
      );

当然,除非您以“正确的方式”对它们进行编号,但将它们“向后”绘制 - 然后只需将我在上面所做的事情颠倒过来即可。 (并不是说我要在这里发动一场宗教战争……)

【讨论】:

  • 有明显的方法可以提高效率。为清楚起见,我将上面的代码保持原样,优化留给读者作为练习。
  • 我会说位的编号对于这个问题并不重要。
  • @jdv - 同意,因为它是对称的。
  • 无符号字符掩码 = 128;字符数 = 0,值 1 = 29;诠释我,一个; for(i = 0; i > a);否则 num = ((value1 & mask) > 1;如果(我 == 7)数 = 数;否则 num = (num | num);
【解决方案2】:

或查找表

以防万一你不明白。这里有更多细节

对于 256 种可能的输入中的每一种都计算出答案(手动)

然后做

unsigned char answers[256] = {0x00, 0x40,0x21.....};
unsigned char answer = answers[input];

我赶紧补充一下,我给出的值是一个例子——而且肯定是不正确的

【讨论】:

  • +1 这个操作看起来非常复杂,256 字节的开销可能是您的最佳选择。
【解决方案3】:

请参阅Bit Twiddling Hacks 上的“反转位序列”部分。

另外,如果你想自己做:

读取第 n 位:int bit = value &amp; (1 &lt;&lt; n); 如果未设置该位,bit 为 0。

设置第 n 位:value |= 1 &lt;&lt; n;(值 = 值或(1 移位 n 位))

要清除第 n 位:value &amp;= ~(1 &lt;&lt; n);(值 = 值与非(1 移位 n 位))

【讨论】:

    【解决方案4】:

    先将低四位与高四位交换,然后交换所有相邻的位对:

    dst = src;
    dst = ((dst & 0xF0) >> 4) | ((dst & 0x0F) << 4);
    dst = ((dst & 0xCC) >> 2) | ((dst & 0x33) << 2);
    

    【讨论】:

      【解决方案5】:

      您可能会发现这很有帮助:

      http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious

      但它的位反转并不是你所需要的。只需一点点工作,您就可以更改“显而易见”的算法来做您想做的事情。

      【讨论】:

        【解决方案6】:
        source byte: [01][23][45][67] to
        destination: [67][45][23][01]
        

        实施:

        unsigned char shiftit( unsigned char in ) {
          unsigned char out;
        
          out = (
            (( in & 0xC0 ) >> 6) + /* top 2 to bottom 2 */
            (( in & 0x30 ) >> 2) + /* centre-left 2 to centre-right */
            (( in & 0x0C ) << 2) + /* centre-right 2 to centre-left */
            (( in & 0x03 ) << 6)   /* bottom 2 to top 2 */
          );
        
          return( out );
        }
        

        调用shiftit( 29 )时返回116。

        【讨论】:

          【解决方案7】:

          循环进位http://en.wikipedia.org/wiki/Bitwise_operation#Rotate_through_carry

          这样就可以了:

          myByte = myByte << 2 | myByte >> 6;
          

          【讨论】:

          • 在汇编程序中很容易,但在 C 中你会如何做到这一点?
          • 它对我有用,但我不知道为什么。确定右移 8 位会产生零吗?
          猜你喜欢
          • 1970-01-01
          • 2021-12-28
          • 2011-03-15
          • 1970-01-01
          • 2014-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-17
          相关资源
          最近更新 更多