自定义 uint16_t 反转函数 returns 0x8000

Custom uint16_t reverse function returns 0x8000

    uint16_t ReverseInt16(uint16_t nonreversed) {
    uint16_t reversed = 0;
    reversed |= (nonreversed & 1 << 15) << 0; //check if bit 15 of nonreversed int is 1, if yes, write 1 to position 0, else write 0 to position 0
    reversed |= (nonreversed & 1 << 14) << 1;
    reversed |= (nonreversed & 1 << 13) << 2;
    reversed |= (nonreversed & 1 << 12) << 3;
    reversed |= (nonreversed & 1 << 11) << 4;
    reversed |= (nonreversed & 1 << 10) << 5;
    reversed |= (nonreversed & 1 << 9) << 6;
    reversed |= (nonreversed & 1 << 8) << 7;
    reversed |= (nonreversed & 1 << 7) << 8;
    reversed |= (nonreversed & 1 << 6) << 9;
    reversed |= (nonreversed & 1 << 5) << 10;
    reversed |= (nonreversed & 1 << 4) << 11;
    reversed |= (nonreversed & 1 << 3) << 12;
    reversed |= (nonreversed & 1 << 2) << 13;
    reversed |= (nonreversed & 1 << 1) << 14;
    reversed |= (nonreversed & 1 << 0) << 15;
    return reversed;
}

我需要位反转 uint16_t,所以我编写了这个函数,它逐位读取原始 uint_t,然后将它们写入另一个 uint,但位位置相反。问题是,当我传递大于 0x00(0) 的整数时,函数 returns 的最大值为 uint16_t。

我是 c 位运算的初学者。

感谢您的回复。

编辑:"Best Algorithm for Bit Reversal ( from MSB->LSB to LSB->MSB) in C" 使用 32 位整数!

我看到两个问题(运算符优先级和错误的移位), 让我们举个例子,您首先要做什么:

reversed |= (nonreversed & 1 << 15) << 0;

运算符优先级有误导性,&的优先级高于<<,那么应该是:

reversed |= (nonreversed & (1 << 15)) << 0;

现在让我们看看它做了什么,想象一下 nonreversed 是 100000000000000b,

然后(非反转 & (1 << 15))是 100000000000000b & 100000000000000b,

这给出 100000000000000b

如果你将它移动0,那么它仍然是100000000000000b (然后第15位不移动到位置0), 因此,如果你想反转位串,你需要说:

reversed |= (nonreversed & (1 << 15)) >> 15;

其他位也一样(注意运算符的优先级,并将位移动到正确的位置)。可以通过循环提高易读性。以下是我将如何实现它:

uint16_t ReverseInt16(uint16_t nonreversed) {
  uint16_t reversed = 0;
  for(uint16_t bit=0; bit<16; ++bit) {
     reversed |= (uint16_t)((nonreversed & (1 << bit) != 0)) << (15 - bit);
  }
  return reversed;
}

表达式 nonreversed & (1 << bit) != 0 是一个布尔值,当转换为 uint16_t 时,如果为假则表示 0,如果为真则表示 1。 1 是我在正确位置移动的位置零位 (<< (15 - bit)).

我想你的意思是:)

#include <stdio.h>
#include <stdint.h>

uint16_t ReverseInt16( uint16_t nonreversed ) 
{
    uint16_t reversed = 0;

    for ( uint16_t i = 0; i < 16; i++ )
    {
        reversed |= ( nonreversed >> ( 16 - i - 1 ) & 1 ) << i;
    }        

    return reversed;
}

int main( void )
{
    uint16_t x = 0x1234;

    printf( "%x\n", x );
    printf( "%x\n", ReverseInt16( x ) );

}    

程序输出为

1234
2c48

至于你的代码,它不会反转位。例如,考虑语句

reversed |= (nonreversed & 1 << 15) << 0;

1 << 15 给出十六进制表示法 8000

然后例如,如果设置了 MSB,那么 (nonreversed & 1 << 15) 也会给出 8000。您需要将结果右移

reversed |= (nonreversed & 1 << 15) >> 15;

但您正试图将其左移

reversed |= (nonreversed & 1 << 15) << 0;

补充一些关于C Operator Precedence

的信息
  • 按位 & 的优先级 低于 <<
    因此,表达式 nonreversed & 1 << 15 等价于 nonreversed & (1 << 15)。但是,最好使用括号来确保优先级。

  • 这是需要括号的典型用法
    if ((a & mask) == flag) //内括号是必需的但容易忘记

  • C 运算符优先级 table