按位运算符从32位获取字节

时间:2011-09-01 23:53:44

标签: c++ c algorithm bit-manipulation

我感兴趣的是编写一个接受两个参数的函数getMyByteChunkFunction - 一个32位整数和一个字节偏移量(0,1,2或3),然后返回32-中的相应字节位整数。例如,给定此整数:

            (3)         (2)      (1)      (0)   ---byte numbers
int word = 10101010 00001001 11001010 00000101

函数调用getMeByteChunkFunction(word, 2)返回00001001

但是,我可以使用的按位运算符有限。我只能使用>><<恰好一个减法。我知道如何使用AND和XOR来做到这一点,但我不知道我在这里如何使用减法。有什么想法吗?

6 个答案:

答案 0 :(得分:25)

一个想法如下。假设您有一个像这样的四字节值:

aaaaaaaa bbbbbbbb cccccccc dddddddd

让我们假设你要从中获取字节bbbbbbbb。如果向右移动两个字节,则得到

???????? ???????? aaaaaaaa bbbbbbbb

这个值等于你想要的值,除了它在顶部有???????? ???????? aaaaaaaa(因为我们不确定转换是否符号保留,因为我不知道你的价值是不是没有签名。不过不用担心;我们可以摆脱这些未知值和a字节。为了摆脱顶部,假设你向右移动另一个字节,给出

???????? ???????? ???????? aaaaaaaa

现在,向左移一个字节来获取

???????? ???????? aaaaaaaa 00000000

如果你再做这个减法,你得到

    ???????? ???????? aaaaaaaa bbbbbbbb
-   ???????? ???????? aaaaaaaa 00000000
---------------------------------------
    00000000 00000000 00000000 bbbbbbbb

瞧......你有你想要的价值!

我会将实际代码作为练习留给读者。别担心;这不是特别难。 : - )

答案 1 :(得分:6)

你只需要换班即可。向左移动以摆脱左侧的位,然后向右移动以摆脱右侧的位并将所需的字节移动到最不重要的位置。

答案 2 :(得分:2)

以下代码也应该回答这个问题。

#include <stdio.h>

int getByte(int x, int n);

void main()
{
    int x = 0xAABBCCDD;
    int n;

    for (n=0; n<=3; n++) {
        printf("byte %d of 0x%X is 0x%X\n",n,x,getByte(x,n));
    }

}

// extract byte n from word x
// bytes numbered from 0 (LSByte) to 3 (MSByte)
int getByte(int x, int n)
{
    return (x >> (n << 3)) & 0xFF;
}

输出

byte 0 of 0xAABBCCDD is 0xDD
byte 1 of 0xAABBCCDD is 0xCC
byte 2 of 0xAABBCCDD is 0xBB
byte 3 of 0xAABBCCDD is 0xAA

这个概念可以根据 templatetypedef 的解释来解释,并扩展如下。

(3)      (2)      (1)      (0)
aaaaaaaa bbbbbbbb cccccccc dddddddd

{(3),(2),(1),(0)} --> {(3)}
  ???????? ???????? ???????? aaaaaaaa // x>>(3*8) where 3 == n
& 00000000 00000000 00000000 11111111 // 0xFF
  -----------------------------------
  00000000 00000000 00000000 aaaaaaaa // (x >> (8 * n)) & 0xFF

{(3),(2),(1),(0)} --> {(2)}
  ???????? ???????? aaaaaaaa bbbbbbbb // x>>(2*8) where 2 == n
& 00000000 00000000 00000000 11111111 // 0xFF  
  -----------------------------------
  00000000 00000000 00000000 bbbbbbbb

{(3),(2),(1),(0)} --> {(1)}
  ???????? aaaaaaaa bbbbbbbb cccccccc // x>>(1*8) where 1 == n
& 00000000 00000000 00000000 11111111 // 0xFF  
  -----------------------------------
  00000000 00000000 00000000 cccccccc

{(3),(2),(1),(0)} --> {(0)}
  aaaaaaaa bbbbbbbb cccccccc dddddddd // x>>(0*8) where 0 == n
& 00000000 00000000 00000000 11111111 // 0xFF  
  -----------------------------------
  00000000 00000000 00000000 dddddddd

Note (x >> (8 * n)) & 0xFF is equivalent to (x >> (n << 3)) & 0xFF.

64 32 16 8 4 2 1 
----------------
0  0  0  0 0 1 1 // (n==3)
0  0  1  1 0 0 0 // (n*8==n<<3==24)
----------------
0  0  0  0 0 1 0 // (n==2)
0  0  1  0 0 0 0 // (n*8==n<<3==16)
----------------
0  0  0  0 0 0 1 // (n==1)
0  0  0  1 0 0 0 // (n*8==n<<3==8)
----------------

答案 3 :(得分:2)

result = (word >> (n_byte << 3)) & 0xFF;

答案 4 :(得分:1)

有一个非常聪明的技巧,我用它将对象转换为char字符串(作为流传输):

//WhichByte should really be an enum to avoid issues
//Counts as 0, 1, 2 or 3
//Modify as unsigned or signed char (for return type and pointer type) as needed
#define BYTE_TYPE unsigned char
BYTE_TYPE GetByte(const unsigned int Source, const unsigned char WhichByte)
{
    if(WhichByte < 0){return 0;}
    if(WhichByte >= sizeof(Source)){return 0;}

    //Converts source into the appropriate pointer
    BYTE_TYPE * C_Ptr = (BYTE_TYPE *)&Source;
    return *(C_Ptr+WhichByte);
}
#undef BYTE_TYPE

简而言之,上面将源视为4个单独的字符(通常只有1个字节),指针允许您将其视为内存部分。你在返回之前取消引用它。

无论用什么目的(甚至是商业用途)都可以使用它。

压缩格式?

#define GetByte(X,Y) (*(((unsigned char *)&X)+Y))

答案 5 :(得分:0)

这是代码:

#include <stdio.h>

int main() {
    unsigned long n = 0xAA09CA05L; /* 10101010 00001001 11001010 00000101 */
    printf("%08lx\n", n); /* input */
    printf("%02lx\n", ((n<<8)>>24)); /* output */
    return 0;
}

和输出:

aa09ca05
09