简体   繁体   中英

4 signed bytes packed into a 32-bit unsigned

// Declaration of data type where 4 bytes are packed into an unsigned.   
int xbyte(packed_t word, int bytenum);

int main()
{
    int bytenum = 0;
    typedef unsigned packed_t;
    packed_t word;
}

// Extract byte from word, return as signed integer.
int xbyte(packed_t word, int bytenum)
{
    // Failed attempt at xbyte
    return ( word >> (bytenum << 3)) & 0xff;
}

I am unsure how to declare the packed_t in this question. I am supposed to use the prototype from the top. How does word even come into play. I am lost this is part of a homework assignment.

You already have a typedef line. Make it the first line of this piece of code, and you are done. The basic thing is that the typedef ed name must be visible everywhere you use it.

First, of course, you can typedef packed_t to any integral type you want; the typedef must be visible everywhere packed_t is used, however.

Secondly, word >> (bytenum << 3) is a bit of obfuscation. What you want is word >> (bytenum * 8) , or even better:

return (word >> (bytenum * CHAR_BIT)) & ((1 << CHAR_BIT) - 1);

(It's hard to say what the best solution is here: the above expression gives portability even to machines where bytes are not 8 bits, but the subexpression to the right of the & is pretty obscure, and certainly worthy of a comment.)

Finally: should we read anything into the title. If you're trying to return the value of the byte as if it were a signed byte, then you'll need additional code to handle that. For a classical 32 bit two's complement machine, the following will work:

int tmp = word >> (bytenum * 8);
if ( (tmp & 0x80) != 0 )
    tmp |= 0xFFFFFF80;
else
    tmp &= 0x7F;
return tmp;

More portably (not that portability to machines which aren't 2's complement with 8 bit bytes is very important), you'd have to write:

int tmp = (word >> (bytenum * CHAR_BIT)) & ((1 << CHAR_BIT) - 1);
if ( tmp > SCHAR_MAX )
    tmp -= UCHAR_MAX + 1;
return tmp;

But this also depends what is actually required. The value of the nth byte depends on the actual representation of integers in hardware. The code above ignores this, and returns the low order byte as byte 0, not necessarily the first byte. If you really want the nth byte some sort of type punning is required:

return *(reinterpret_cast<signed char*>( &word ) + bytenum);

Without more information as to what is required, it's difficult to say what the correct answer should be.

perhaps a union would be useful here

union packed_t
{
    unsigned int unsignedInt;
    char signedChar[4];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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