Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the expression below characterize a narrowing conversion?

This expression can be found in the Example in §8.5.4/7 in the Standard (N3797)

unsigned int ui1 = {-1}; // error: narrows

Given §8.5.4/7 and its 4th bullet point:

A narrowing conversion is an implicit conversion:

  • from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

I would say there's no narrowing here, as -1 is a constant expression, whose value after integral promotion fits into an unsigned int.

See also §4.5/1 about Integral Promotion:

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

From 4.13 we have that the rank of -1 (an int) is equal to the rank of an unsigned int, and so it can be converted to an unsigned int.

Edit

Unfortunately Jerry Coffin removed his answer from this thread. I believe he was on the right track, if we accept the fact that the current reading of the 4th bullet point in §8.5.4/7 is wrong, after this change in the Standard.

like image 820
Wake up Brazil Avatar asked Jan 20 '14 19:01

Wake up Brazil


3 Answers

There is no integral promotion from int to unsigned int, therefor it is still illformed.

That would be an integral conversion.

like image 102
Johannes Schaub - litb Avatar answered Oct 11 '22 21:10

Johannes Schaub - litb


The change in the wording of the standard is intended to confirm the understanding that converting a negative value into an unsigned type is and always has been a narrowing conversion.

Informally, -1 cannot be represented within the range of any unsigned type, and the bit pattern that represents it does not represent the same value if stored in an unsigned int. Therefore this is a narrowing conversion and promotion/widening is not involved.

This is about the dainty art of reading the standard. As usual, the compiler knows best.

like image 45
david.pfx Avatar answered Oct 11 '22 22:10

david.pfx


Narrowing is an implicit conversion from an integer type to an integer type that cannot represent all the values of the original type

Conversion from integer type int to integer type unsigned int, of course, cannot represent all the values of the original type -- the standard is quite unambigious here. If you really need it, you can do

 unsigned int ui1 = {-1u};

This works without any errors/warnings since 1u is a literal of type unsigned int which is then negated. This is well-defined as [expr.unary.op] in the standard states:

The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the promoted operand.

-1 however is an int before and after the negation and hence it becomes a narrowing conversion. There are no negative literals; see this answer for details.

Promotion is, informally, copying the same value into a larger space, so it shouldn't be confused here as the sizes (of signed and unsigned) are equal. Even if you try to convert it to some type of larger size, say unsigned long long it's still a narrowing conversion as it cannot represent a negative number truly.

like image 1
legends2k Avatar answered Oct 11 '22 21:10

legends2k