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

时间:2022-05-02 20:19:47

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. For example, given this integer:

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

            (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. Any ideas?

但是,我可以使用的位运算符是有限的。我只允许使用>>,<<,而且只有一个减法。我知道怎么用x和XOR,但我不知道怎么用减法。什么好主意吗?

6 个解决方案

#1


25  

One idea is as follows. Suppose that you have a four-byte value like this one:

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

aaaaaaaa bbbbbbbb cccccccc dddddddd

Let's suppose that you want to get the byte bbbbbbbb out of this. If you shift right by two bytes, you get

让我们假设你想要从这里得到一个字节bbbbbbbb。如果右移两个字节,就会得到。

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

This value is equal to what you want, except that at the top it has ???????? ???????? 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; we can get rid of these unknown values and the a byte. To get rid of the top, suppose that you shift right another byte, giving

这个值等于你想要的值,除了在顶部它有????????? ? ? ? ? ? ? ?aaaaaaaa(因为我们不确定这一转换是否保留,因为我不知道您的值是否没有签名。)不用担心,虽然;我们可以去掉这些未知的值和一个字节。为了去掉顶部,假设右移另一个字节,给出。

???????? ???????? ???????? 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. :-)

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

#2


6  

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.

你可以用移动来做。左移来处理左边的位元,然后右移来处理右边的位元,并将需要的字节移到最不重要的位置。

#3


2  

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)
----------------

#4


2  

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

#5


1  

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. You dereference it before return.

简而言之,上面的处理源是4个单独的chars(通常只有一个字节大小),并且指针允许您将它作为一个内存部分来处理。你在返回之前将其取消。

Use it whatever purpose (even commercial).

无论出于什么目的(甚至是商业目的),都要使用它。

Compressed format?

压缩格式吗?

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

#6


0  

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

#1


25  

One idea is as follows. Suppose that you have a four-byte value like this one:

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

aaaaaaaa bbbbbbbb cccccccc dddddddd

Let's suppose that you want to get the byte bbbbbbbb out of this. If you shift right by two bytes, you get

让我们假设你想要从这里得到一个字节bbbbbbbb。如果右移两个字节,就会得到。

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

This value is equal to what you want, except that at the top it has ???????? ???????? 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; we can get rid of these unknown values and the a byte. To get rid of the top, suppose that you shift right another byte, giving

这个值等于你想要的值,除了在顶部它有????????? ? ? ? ? ? ? ?aaaaaaaa(因为我们不确定这一转换是否保留,因为我不知道您的值是否没有签名。)不用担心,虽然;我们可以去掉这些未知的值和一个字节。为了去掉顶部,假设右移另一个字节,给出。

???????? ???????? ???????? 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. :-)

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

#2


6  

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.

你可以用移动来做。左移来处理左边的位元,然后右移来处理右边的位元,并将需要的字节移到最不重要的位置。

#3


2  

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)
----------------

#4


2  

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

#5


1  

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. You dereference it before return.

简而言之,上面的处理源是4个单独的chars(通常只有一个字节大小),并且指针允许您将它作为一个内存部分来处理。你在返回之前将其取消。

Use it whatever purpose (even commercial).

无论出于什么目的(甚至是商业目的),都要使用它。

Compressed format?

压缩格式吗?

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

#6


0  

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

相关文章