Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why auto is deduced to int instead of uint16_t

I have the following code:

uint16_t getLastMarker(const std::string &number);
...
const auto msgMarker = getLastMarker(msg.number) + static_cast<uint16_t>(1);
static_assert(std::is_same<decltype(msgMarker), const int>::value, "Should fail");
static_assert(std::is_same<decltype(msgMarker), const uint16_t>::value, "Should not fail");

and I expect that the first assertion will fail and second one will not. However gcc 4.9.2 and clang 3.6 do the opposite. If I use uint16_t instead of auto in my code proper assertion fails and another one succeeds.

P.S. Initially I had just 1 instead of static_cast<uint16_t>(1) and thought that the issue is caused by the fact that numeric literal 1 has type int but wrong assertion fails even after explicit cast here.

like image 674
VestniK Avatar asked May 12 '15 13:05

VestniK


People also ask

What is the difference between int and uint16_t?

int is usually (but may not be) a 32-bit signed integer, while uint16_t is guaranteed to be an unsigned 16-bit integer.

What does uint16_t represent in C?

uint16_t is unsigned 16-bit integer. unsigned short int is unsigned short integer, but the size is implementation dependent. The standard only says it's at least 16-bit (i.e, minimum value of UINT_MAX is 65535 ).


2 Answers

Addition will perform the usual arithmetic conversions on its operands which in this case will result in the operands being promoted to int due the the integer promotions and the result will also be int.

You can use uint16_t instead of auto to force a conversion back or in the general case you can use static_cast.

For a rationale as to why type smaller than int are promoted to larger types see Why must a short be converted to an int before arithmetic operations in C and C++?.

For reference, from the draft C++ standard section 5.7 Additive operators:

[...]The usual arithmetic conversions are performed for operands of arithmetic or enumeration type[...]

and from section 5 Expressions:

[...]Otherwise, the integral promotions (4.5) shall be performed on both operands.59 Then the following rules shall be applied to the promoted operands[...]

and from section 4.5 Integral promotions (emphasis mine):

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.

Assuming int is larger than 16-bit.

like image 188
Shafik Yaghmour Avatar answered Sep 17 '22 15:09

Shafik Yaghmour


Arithmetic operations don't work on any type smaller than int. So, if uint16_t is smaller than int, it will be promoted to int (or possibly a larger type, if necessary to match the other operand) before performing the addition.

The result of the addition will be the promoted type. If you want another type, you'll have to convert afterwards.

like image 30
Mike Seymour Avatar answered Sep 20 '22 15:09

Mike Seymour