自定义 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
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