简体   繁体   English

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

[英]Bitwise operator to get byte from 32 bits

I am interested in writing a function getMyByteChunkFunction that accepts two parameters - a 32-bit integer and a byte offset (0, 1, 2, or 3), then returns the corresponding byte out of the 32-bit integer. 我有兴趣编写一个函数getMyByteChunkFunction ,它接受两个参数 - 一个32位整数和一个字节偏移量(0,1,2或3),然后从32位整数中返回相应的字节。 For example, given this integer: 例如,给定此整数:

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

the function call getMeByteChunkFunction(word, 2) returns 00001001 . 函数调用getMeByteChunkFunction(word, 2)返回00001001

However, I am limited in the bitwise operators I can use. 但是,我可以使用的按位运算符有限。 I am only allowed to use >> , << , and exactly one subtraction. 我只允许使用>><<一个减法。 I know how to do this using AND and XOR, but I don't know how I'd use a subtraction here. 我知道如何使用AND和XOR来做到这一点,但我不知道我在这里如何使用减法。 Any ideas? 有任何想法吗?

One idea is as follows. 一个想法如下。 Suppose that you have a four-byte value like this one: 假设您有一个像这样的四字节值:

aaaaaaaa bbbbbbbb cccccccc dddddddd

Let's suppose that you want to get the byte bbbbbbbb out of this. 让我们假设你想要得到字节bbbbbbbb If you shift right by two bytes, you get 如果你向右移动两个字节,你得到

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

This value is equal to what you want, except that at the top it has ???????? ???????? aaaaaaaa 这个值等于你想要的值,除了顶部它有???????? ???????? aaaaaaaa ???????? ???????? aaaaaaaa ???????? ???????? aaaaaaaa (because we're not sure if the shift is sign-preserving or not, since I don't know if your value is unsigned or not.) No worries, though; ???????? ???????? aaaaaaaa (因为我们不确定这种转变是否符号保留,因为我不知道你的价值是否未签名。)不用担心; we can get rid of these unknown values and the a byte. 我们可以摆脱这些未知值和a字节。 To get rid of the top, suppose that you shift right another byte, giving 为了摆脱顶部,假设你向右移动另一个字节,给予

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

Now, shift left one byte to get 现在,向左移一个字节来获取

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

If you then do this subtraction, you get 如果你然后做这个减法,你得到

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

And voilà... you've got the value you want! 瞧......你有你想要的价值!

I'll leave the actual code as an exercise to the reader. 我会将实际代码作为练习留给读者。 Don't worry; 别担心; it's not particularly hard. 这不是特别难。 :-) :-)

You can do it just with shifting. 你只需要换班就可以做到。 Shift left to get rid of the bits on the left, then shift right to get rid of the bits on the right and move the wanted byte into the least significant spot. 向左移动以摆脱左侧的位,然后向右移动以摆脱右侧的位并将所需的字节移动到最不重要的位置。

The following code should also answer the question. 以下代码也应该回答这个问题。

#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;
}

The output is 输出是

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

The concept can be explained based on templatetypedef 's explanation and expanded as follows. 这个概念可以基于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)
----------------
result = (word >> (n_byte << 3)) & 0xFF;

There's a very clever trick for this, which I use for converting objects into char strings (to transmit as a stream): 有一个非常聪明的技巧,我用它将对象转换为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

In short, the above treats source as 4 separate chars (which are normally only 1 byte in size), and the pointer allows you to treat it as a memory section. 简而言之,上面将源视为4个单独的字符(通常只有1个字节),指针允许您将其视为内存部分。 You dereference it before return. 你在返回之前取消引用它。

Use it whatever purpose (even commercial). 无论用途(甚至是商业用途)都可以使

Compressed format? 压缩格式?

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

here is the code: 这是代码:

#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;
}

and the output: 和输出:

aa09ca05
09

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM