c - How can an (int) be converted to (unsigned int) while preserving the original bit pattern? -
suppose define:
short x = -1; unsigned short y = (unsigned short) x;
according c99 standard:
otherwise, if new type unsigned, value converted repeatedly adding or subtracting 1 more maximum value can represented in new type until value in range of new type. (iso/iec 9899:1999 6.3.1.3/2)
so, assuming 2 bytes short , two's complement representation, bit patterns of these 2 integers are:
x = 1111 1111 1111 1111 (value of -1), y = 1111 1111 1111 1111 (value of 65535).
since -1 not in value range unsigned short, , maximum value can represented in unsigned short 65535, 65536 added -1 65535, in range of unsigned short. bits remain unchanged in casting int unsigned, though represented value changed.
but, standard says representations may two's complement, one's complement, or sign , magnitude. "which of these applies implementation-defined,...." (iso/iec 9899:1999 6.2.6.2/2)
on system using one's complement, x
represented 1111 1111 1111 1110
before casting, , on system using sign , magnitude representation, x
represented 1000 0000 0000 0001
. both of these bit patterns represent value of -1, not in value range of unsigned short, 65536 added -1 in each case bring values range. after cast, both of these bit patterns 1111 1111 1111 1111
.
so, preservation of bit pattern in casting int unsigned int implementation dependent.
it seems ability cast int unsigned int while preserving bit pattern handy tool doing bit-shifting operations on negative numbers, , have seen advocated technique that. technique not appear guaranteed work standard.
am reading standard correctly here, or misunderstanding details of conversion signed unsigned types? two's complement implementations prevalent enough assumption of bit-pattern preservation under casting int unsigned reasonable? if not, there better way preserve bit patterns under conversion int unsigned int?
edit
my original goal find way cast int unsigned int in such way bit pattern preserved. thinking cast int intn_t accomplish this:
unsigned short y = (unsigned short)(int16_t) x;
but of course idea wrong! @ best enforce two's complement representation before casting unsigned, final bit pattern two's complement. tempted delete question, yet still interested in ways cast int unsigned int preserve bit patterns, , @leushenko has provided neat solution problem using unions. but, have changed title of question reflect original intention, , have edited closing questions.
is acceptable cast
(int)
(unsigned)(intn_t)
preserve bit patterns?
often, yes, not specified in c values. c tries maintain values during type conversions, not bit patterns.
should value, x
, representable int
, unsigned
, chosen intn_t
, value's bit pattern not change. question relates when x
negative.
c specifies conversion unsigned type cope overflow add/subtracting "maximum value of unsigned type + 1" until result in range. should signed type use 2's complement encoding, pattern of lower significant bits match target unsigned type.
conversion signed integer types in implementation defined behavior - hence op's dilemma.
c specifies range of signed integer type , corresponding unsigned integer type both need encode rage: 0
signed type maximum. iows int_max == uint_max
allowed. on such rare platforms, converting int
unsigned
int
loses sign.
if code needs preserve signed type's bit pattern, union
array of unsigned char
works in cases.
union ua { some_signed_int_type i; unsigned char uc[sizeof (some_signed_int_type)]; }
a union fixed-width unsigned type (these types optional) maximum greater signed maximum works maintain bit pattern. not rely on value being same, positive values. fixed width types not have padding, not general signed types.
assert(uintn_max > some_signed_type_max); union ub { some_signed_int_type i; uintn_t u; }
the central benefit of unsigned char
, (u)intn_t
these types specified not have padding.
Comments
Post a Comment