反转半字节
Reversing the nibbles
我正在尝试“通过反转其半字节来构建一个新数字”。
这是练习:
Write a function that given an unsigned n
a) returns the value with the nibbles placed in reverse order
我在想32位无符号的所有8个半字节应该倒序放置。因此,以数字 24 为例,它是 00000000000000000000000000011000。
=> 反向值应为:10000001000000000000000000000000.
#include <stdio.h>
unsigned getNibble(unsigned n,unsigned p){
unsigned mask = 0xFu;
unsigned nibble = 0;
nibble = (n&(mask<<p))>>p;
return nibble;
}
unsigned swapNibbles(unsigned n){
unsigned new = 0;
unsigned nibble;
for(unsigned i=0;i<(sizeof(n)*8);i=i+4){
nibble = getNibble(n,i);
new = (new<<i) + nibble;
}
return new;
}
int main(void) {
printf("0x%x",swapNibbles(24));
return 0;
}
我试过调试它,直到一点都还不错。
在一次右移时,它将我的“新”变量转换为 0。
并行工作的方法:
uint32_t n = ...;
// Swap the nibbles of each byte.
n = (n & 0x0F0F0F0F ) << 4
| (n & 0xF0F0F0F0 ) >> 4;
// Swap the bytes of each byte pair.
n = ( n & 0x00FF00FF ) << 8
| ( n & 0xFF00FF00 ) >> 8;
// Swap the byte pairs.
n = ( n & 0x0000FFFF ) << 16
| ( n & 0xFFFF0000 ) >> 16;
并行工作大大减少了操作次数。
OP's This
Approach Approach
-------- --------- ---------
Shifts 24 / 48 6 / 8 32 bits / 64 bits
Ands 8 / 16 6 / 8
Ors* 8 / 16 3 / 4
Assigns 8 / 16 3 / 4
Adds 8 / 16 0 / 0
Compares 8 / 16 0 / 0
-------- --------- ---------
Total 64 / 128 18 / 24
-------- --------- ---------
Scale O(N) O(log(N))
* Addition was used as "or" in the OP's solution.
此声明
new = (new << i) + nibble;
错了。应该有
new = (new << 4) + nibble;
int main (void)
{
uint32_t x = 0xDEADBEEF;
printf("original 4 bytes %X\n", x);
uint32_t y = 0;
for(uint8_t i = 0 ; i < 32 ; i += 4)
{
y <<= 4;
y |= x>>i & 0xF;
}
printf("reverse order nibbles %X\n", y);
return 0;
}
这可以成为接受所有 8、16、32 位数字的通用函数。但现在这解决了您在代码中面临的错误。
但我要指出 ikegami 的代码比这种方法要好得多。
我正在尝试“通过反转其半字节来构建一个新数字”。
这是练习:
Write a function that given an unsigned n
a) returns the value with the nibbles placed in reverse order
我在想32位无符号的所有8个半字节应该倒序放置。因此,以数字 24 为例,它是 00000000000000000000000000011000。 => 反向值应为:10000001000000000000000000000000.
#include <stdio.h>
unsigned getNibble(unsigned n,unsigned p){
unsigned mask = 0xFu;
unsigned nibble = 0;
nibble = (n&(mask<<p))>>p;
return nibble;
}
unsigned swapNibbles(unsigned n){
unsigned new = 0;
unsigned nibble;
for(unsigned i=0;i<(sizeof(n)*8);i=i+4){
nibble = getNibble(n,i);
new = (new<<i) + nibble;
}
return new;
}
int main(void) {
printf("0x%x",swapNibbles(24));
return 0;
}
我试过调试它,直到一点都还不错。 在一次右移时,它将我的“新”变量转换为 0。
并行工作的方法:
uint32_t n = ...;
// Swap the nibbles of each byte.
n = (n & 0x0F0F0F0F ) << 4
| (n & 0xF0F0F0F0 ) >> 4;
// Swap the bytes of each byte pair.
n = ( n & 0x00FF00FF ) << 8
| ( n & 0xFF00FF00 ) >> 8;
// Swap the byte pairs.
n = ( n & 0x0000FFFF ) << 16
| ( n & 0xFFFF0000 ) >> 16;
并行工作大大减少了操作次数。
OP's This
Approach Approach
-------- --------- ---------
Shifts 24 / 48 6 / 8 32 bits / 64 bits
Ands 8 / 16 6 / 8
Ors* 8 / 16 3 / 4
Assigns 8 / 16 3 / 4
Adds 8 / 16 0 / 0
Compares 8 / 16 0 / 0
-------- --------- ---------
Total 64 / 128 18 / 24
-------- --------- ---------
Scale O(N) O(log(N))
* Addition was used as "or" in the OP's solution.
此声明
new = (new << i) + nibble;
错了。应该有
new = (new << 4) + nibble;
int main (void)
{
uint32_t x = 0xDEADBEEF;
printf("original 4 bytes %X\n", x);
uint32_t y = 0;
for(uint8_t i = 0 ; i < 32 ; i += 4)
{
y <<= 4;
y |= x>>i & 0xF;
}
printf("reverse order nibbles %X\n", y);
return 0;
}
这可以成为接受所有 8、16、32 位数字的通用函数。但现在这解决了您在代码中面临的错误。
但我要指出 ikegami 的代码比这种方法要好得多。