【问题标题】:Custom uint16_t reverse function returns 0x8000自定义 uint16_t 反向函数返回 0x8000
【发布时间】:2015-07-15 21:12:05
【问题描述】:
    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) 的整数时,函数返回 uint16_t 的最大值。

我是 c 位运算的初学者。

感谢您的回复。

编辑:“C 中位反转的最佳算法(从 MSB->LSB 到 LSB->MSB)”使用 32 位整数!

【问题讨论】:

标签: c bit-manipulation reverse bit-shift masking


【解决方案1】:

我看到两个问题(运算符优先级和错误班次), 让我们举个例子,你首先做了什么:

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

运算符优先级有误导性,&的优先级高于

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

现在让我们看看它的作用,假设 nonreversed 是 100000000000000b,

则 (非反转 & (1

这给出了 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

【讨论】:

  • 是的,我知道了,但是您包含的代码返回 0 :/
  • for(uint16_t bit=0; bit&lt;15; 只进行 15 次迭代,当然需要 16 次。
  • 当!你是对的,谢谢你的关注! (已编辑)
【解决方案2】:

我认为你的意思是:)

#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 &lt;&lt; 15 以十六进制表示法8000

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

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

但你正试图将它向左移动

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

【讨论】:

  • 先生,非常感谢您的帮助!它在第一次尝试时有效!祝你今天过得愉快! :)
【解决方案3】:

补充一些关于C Operator Precedence的信息,

  • 按位计算&amp; 的优先级低于&lt;&lt;
    所以,表达式nonreversed &amp; 1 &lt;&lt; 15 等价于nonreversed &amp; (1 &lt;&lt; 15)。但是,最好使用括号来确保优先级。

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

  • C 运算符优先级表

【讨论】:

    猜你喜欢
    • 2018-02-21
    • 2020-08-20
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多