Why does the expression below characterize a narrowing conversion?
Asked Answered
E

3

8

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.

Exalted answered 20/1, 2014 at 19:4 Comment(3)
No. It is a integer already (a signed integer), after conversion it's value does not fit into the target type. An unisgned integer cannot represent all the values of a signed integer, specifically; it cannot represent a negative value.Af
"-1 is a constant expression, whose value after integral promotion fits into an unsigned int." - no, -1 is of type int, and as such, it's not promoted to anything.Irritable
@ElliottFrisch If you view an unsigned integer as a positive integer is can't, if you view as a modular integer it can!!Hidie
K
1

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.

Kinnon answered 21/1, 2014 at 14:3 Comment(5)
Therefore this is a narrowing conversion and promotion/widening is not involved. Where does it say in the Standard that an integral promotion doesn't apply in this case? By the contrary, the bullet point I highlighted in my question mentions specifically the term integral promotion.Exalted
@Wake: S6.3.1.1 defines integer promotions. They only apply to a value of lower rank, or a bit field, and they preserve sign. They never operate to convert a signed integer into unsigned. Other references to integer promotions do not change this definition.Kinnon
I don't know of any 6.3.1.1 or S6.3.1.1 in the drafts N3337 and N3797. Integral promotion is defined in §4.5 in both drafts and the paragraph that I alluded in my question is the very first paragraph in this section of the Standard. According to this paragraph, definitely, -1 can be promoted to an unsigned int. And this occurs because the rank of an int is equal to the rank of an unsigned int (from §4.13).Exalted
Oops. Sorry, I was in the C standard there. Does not change the situation. I think you are reading the 'otherwise' in S4.5 as if it applied to every integer type and it does not. It only applies to the last if, the bit about representing all the values. Since int is not 'less than the rank of int', nothing in that para applies to int. In short, int is never promoted.Kinnon
(+1) You nailed it! Excellent answer. TksExalted
H
7

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

That would be an integral conversion.

Hexylresorcinol answered 20/1, 2014 at 19:7 Comment(4)
Could you explain this in terms of §4.5/1?Exalted
I think this answer agrees with the issue that removed the text @JerryCoffin has highlighted.Guttersnipe
@WakeupBrazil honestly I have no idea how to explain any better than the text does. It says just what I said in the answer, and much more elaborate and detailed at it.Hexylresorcinol
@Joh: not illformed, just narrowing.Kinnon
Y
1

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.

Yashmak answered 20/1, 2014 at 19:12 Comment(3)
I think a compiler could legitimately emit a warning for -1u.Kinnon
That's interesting. So int to unsigned int is narrowing, and by the same definition, unsigned int to int is also narrowing?Stodge
Yes, for unsigned x = 0u; signed y = {x}; GCC (4.8.1) spits: warning: narrowing conversion of 'x' from 'unsigned int' to 'int' inside { }.Yashmak
K
1

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.

Kinnon answered 21/1, 2014 at 14:3 Comment(5)
Therefore this is a narrowing conversion and promotion/widening is not involved. Where does it say in the Standard that an integral promotion doesn't apply in this case? By the contrary, the bullet point I highlighted in my question mentions specifically the term integral promotion.Exalted
@Wake: S6.3.1.1 defines integer promotions. They only apply to a value of lower rank, or a bit field, and they preserve sign. They never operate to convert a signed integer into unsigned. Other references to integer promotions do not change this definition.Kinnon
I don't know of any 6.3.1.1 or S6.3.1.1 in the drafts N3337 and N3797. Integral promotion is defined in §4.5 in both drafts and the paragraph that I alluded in my question is the very first paragraph in this section of the Standard. According to this paragraph, definitely, -1 can be promoted to an unsigned int. And this occurs because the rank of an int is equal to the rank of an unsigned int (from §4.13).Exalted
Oops. Sorry, I was in the C standard there. Does not change the situation. I think you are reading the 'otherwise' in S4.5 as if it applied to every integer type and it does not. It only applies to the last if, the bit about representing all the values. Since int is not 'less than the rank of int', nothing in that para applies to int. In short, int is never promoted.Kinnon
(+1) You nailed it! Excellent answer. TksExalted

© 2022 - 2024 — McMap. All rights reserved.