Reputation: 1847
In Beej's Guide to Network Programming, there is a function that was meant to provide a portable way to serialize a 16-bit integer.
/*
** packi16() -- store a 16-bit int into a char buffer (like htons())
*/
void packi16(unsigned char *buf, unsigned int i)
{
*buf++ = i>>8; *buf++ = i;
}
I don't understand why the statement *buf++ = i;
is portable, as the assignment of an unsigned integer (i
) to an unsigned character (*buf
) would result in a narrowing conversion.
unsigned int
is always truncated and its least significant 8 bits are retained in the unsigned char
?If not, is there any preferred way to fix the issue? Is it adequate to change the function body to the following?
*buf++ = (i>>8) & 0xFFFFU; *buf++ = i & 0xFFFFU;
Upvotes: 1
Views: 1190
Reputation: 145279
The code assumes an 8-bit byte, and that is not portable.
E.g. some Texas Instruments digital signal processors have 16-bit byte.
The number of bits per byte is given by CHAR_BIT
from <limits.h>
.
Also, the code assumes that unsigned
is 16 bits, which is not portable.
In summary the code is not portable.
Re
” Does the C++ standard guarantees that in such a conversion, the unsigned int is always truncated and its least significant 8 bits are retained in the unsigned char?
No, since the C++ standard does not guarantee that the number of bits per byte is 8.
The only guarantee is that it's at least 8 bits.
Unsigned arithmetic is guaranteed modular, however.
Re
” If not, is there any preferred way to fix the issue?
Use a simple loop, iterating sizeof(unsigned)
times.
The code in question appears to have been distilled from such a loop, since the post-increment in *buf++ = i;
is totally meaningless (this is the last use of buf
).
Upvotes: 3
Reputation: 141618
Yes, out-of-range assignments to unsigned types adjust the value modulo one greater than the maximum value representable in the type. In this case, mod UCHAR_MAX+1
.
No fix is required. Some people like to write *buf++ = i % 0x100;
or equivalent, to make it clear that this was intentional narrowing.
Upvotes: 1