【问题标题】:How to swap nibbles in C?如何在C中交换半字节?
【发布时间】:2011-12-13 04:06:34
【问题描述】:

如何交换数字的半字节位置?

例如:534,将其转换成二进制,最右边的4位必须与最左边的4位互换,然后用它做一个新的数字。

有人知道怎么做吗?

【问题讨论】:

  • 您能更清楚地说明问题吗? 534 不适合 8 位 - 您的意思是 16 位数字,如果是,您要交换哪些半字节?
  • 只考虑大约 8 位! :)
  • 这就是为什么你应该在学习编程之前学习二进制和十六进制...

标签: c bit-manipulation


【解决方案1】:

Sean Anderson's bit twiddling guide 有以下内容:

// swap nibbles ... 
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);

Reverse an N-bit quantity in parallel in 5 * lg(N) operations 的条目下。

【讨论】:

  • 我在一个网站上看到了这个例子。unsigned char c= 0x34; temp1 = c &amp; 0x0F; temp2 = c &amp; 0xF0; temp1=temp1 &lt;&lt; 4; temp2=temp2 &gt;&gt; 4; return(temp2|temp1);这是什么意思?
  • 您忘记使用 sizeof 确保位掩码大小正确,记住 C 中没有大小保证
【解决方案2】:

从十六进制0xf 正好覆盖四位这一事实开始。一个 16 位数字中有四个半字节。半字节的掩码是0xf0000xf000xf00xf。然后开始屏蔽、移位和按位 OR-ing。

【讨论】:

  • 其实0x0F和0xF0有什么区别?
  • 0xf0 是十进制的 240,而 0x0f 是 15。
  • 我在一个网站上看到了这个例子。unsigned char c= 0x34; temp1 = c &amp; 0x0F; temp2 = c &amp; 0xF0; temp1=temp1 &lt;&lt; 4; temp2=temp2 &gt;&gt; 4; return(temp2|temp1);这是什么意思?
  • 表示:将值0x34赋给c;将 c 的低 4 位存储在 temp1 中;将 c 的前 4 位存储在 temp2 中;将 temp1 中的位向左移动 4 位;将 temp2 中的位右移 4 位;或 temp2 和 temp1 一起创建一个 8 位值。做一些谷歌搜索位操作,它会更有意义。
【解决方案3】:

1)

y = ((x >> 4) & 0x0f) | ((x << 4) & 0xf0);

2)

unsigned char swap_nibbles(unsigned char c)
{
     unsigned char temp1, temp2;

     temp1 = c & 0x0F;
     temp2 = c & 0xF0;
     temp1=temp1 << 4;
     temp2=temp2 >> 4;

     return(temp2|temp1); //adding the bits
}

3)

unsigned char nibbleSwap(unsigned char a)
{
    return (a<<4) | (a>>4);
}

【讨论】:

    【解决方案4】:
    //program to swap nibbles from 32 bit number swap
    #include <stdio.h>
    #include <stdint.h>
    
    int main()
    {
     uint32_t n = 0x10203040;
     uint32_t swaped_no=0;
     int data;
     char shift = 0;
     for(int i =0;i<4;i++)
     {
      data= n>>shift;
      data = (((data & 0x0F)<<4) | ((data & 0xF0)>>4));
      swaped_no = swaped_no | (data<<shift);
      shift=shift+8;
     }
     printf("swapped no 0x%08x",swaped_no);
    }
    

    没有交换 0x01020304

    【讨论】:

    • 你介意用一致的缩进修正代码并让 main 实际上返回一些东西吗?网站中显示的代码应该是高质量的,并且尽可能干净地通过代码审查。
    【解决方案5】:

    如果 swap 更像是 32 位 endiness 转换,则以下 API 必须工作:

    uint32 decode_32le(uint8 *p)
    {
    return ( p[0] | (p[1] << 8) | (p[2] << 16) |(p[3]<<24));
    }
    

    *这里它将交换仅由 malloc/calloc 分配的连续内存位置/字节,而不是数组。

    【讨论】:

    • 请注意,这是为了从字节数组中重建一个 32 位整数。它对主机处理器的endianness 进行了假设,因此不能在程序中盲目使用——必须有一个对应的decode_32le() 例程在相反字节序的平台上工作,以防此代码在这样的平台上编译.它也与nibble 交换无关,因为它排列字节
    • 是的,你说得对。因此,我已经提到了它的 32 位 Endiness 交换。感谢您提供更多说明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    相关资源
    最近更新 更多