反转半字节

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 的代码比这种方法要好得多。