xbyte said:
It's a problem from a book, and I can't figure it out.
4 words (4x8 bits) are packed into a 32-bit unsigned integer, and
you've gotta extract an indicated (by bytenum) word from it, AND the
following code is said to be written by a failed programmer:
int xbyte(unsigned word, int bytenum)
{
return (word >> (bytenum << 3)) & 0xFF;
}
IMHO, this is a perfect bulk of code, what's your opinion?
Perfect is a strong word! I'd say it captures the gist of the
problem but it is not portable and will exhibit undefined behaviour
is some cases.
Unsigned types are a natural choice when doing bit operations, so I'd
prefer an unsigned return type (unless the integer return is used to
signal an error using a negative value).
The bytenum can not be negative, so why not make that unsigned? In
any case, undefined behaviour awaits if bytenum is out of range.
Personally, I prefer '* 8' to '<< 3' when multiplying by 8.
C99 provides a good type to document the 32-bit assumption: uint32_t
but slightly greater portability can be got by using uint_least32_t.
Thus:
uint_least8_t xbyte(uint_least32_t word, unsigned bytenum)
{
assert(bytenum < 4);
return (word >> (bytenum * 8)) & 0xff;
}
or maybe:
int xbyte(uint_least32_t word, unsigned bytenum)
{
return bytenum < 4 ? (word >> (bytenum * 8)) & 0xff : -1;
}
In C90, I'd probably write:
unsigned char xbyte(unsigned long word, unsigned bytenum)
{
assert(bytenum < 4);
return (word >> (bytenum * 8)) & 0xff;
}
or
int xbyte(unsigned long word, unsigned bytenum)
{
return bytenum < 4 ? (word >> (bytenum * 8)) & 0xff : -1;
}
but I would never say any of these is perfect (for one thing that
would imply that code can be unambiguously ordered by "quality").