Reputation: 61378
Does the C++ standard guarantee whether integer conversion that both widens and casts away the sign will sign-extend or zero-extend?
The quick test:
int32_t s = -1;
uint64_t u = s;
produces an 0xFFFFFFFFFFFFFFFF under Xcode, but is that a defined behavior in the first place?
Upvotes: 4
Views: 1564
Reputation: 136296
You can find the standard verbiage in other answers.
But to help you form an intuitive mental model of widening conversions, it is helpful to think of these as a 2-step process:
int32_t
is sign-extended to int64_t
. On x86, the signedness of type detetermines whether MOVSX
or MOVZX
instruction is used.int64_t
is converted to uint64_t
. It involves 0 assembly instructions as registers are untyped, the compiler just treats that register, which contains the result of sign extension of int32_t
, as uint64_t
.Note that the standard doesn't specify these steps, it just specifies the required result.
Upvotes: 2
Reputation: 180660
When you do
uint64_t u = s;
[dcl.init]/17.9 applies which states:
the initial value of the object being initialized is the (possibly converted) value of the initializer expression. A standard conversion sequence ([conv]) will be used, if necessary, to convert the initializer expression to the cv-unqualified version of the destination type; no user-defined conversions are considered.
and if we look in [conv], under integral conversions, we have
Otherwise, the result is the unique value of the destination type that is congruent to the source integer modulo 2N, where N is the width of the destination type.
So what you are guaranteed to have happen is that -1 becomes the largest number possible to represent, -2 is one less then that, -3 is one less then -2 and so on, basically it "wraps around".
In fact,
unsigned_type some_name = -1;
Is the canonical way to create a variable with the maximum value for that unsigned integer type.
Upvotes: 4
Reputation: 17454
From the section on Integral conversions:
[conv.integral/3]:
Otherwise, the result is the unique value of the destination type that is congruent to the source integer modulo 2N, where N is the width of the destination type.
In other words, the wrap-around "happens last".
Upvotes: 1