Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does uint8_t + uint8_t results in an int? [duplicate]

Tags:

c++

types

It came to my attention that for simple operations on 8bit variables, the variables get converted to 32bit ints before the operation is done, and then converted back to 8bit variables.

As an example, this c++ program:

#include <iostream>
#include <cstdint>

int main( void )
{
  uint8_t a = 1;
  uint8_t b = 2;

  std::cout << "sizeof(a)   = " << sizeof( a ) << std::endl;
  std::cout << "sizeof(b)   = " << sizeof( b ) << std::endl;
  std::cout << "sizeof(a+b) = " << sizeof( a+b ) << std::endl;

  return 0;
}

Produces the following output:

sizeof(a)   = 1
sizeof(b)   = 1
sizeof(a+b) = 4

So we could understand that what happens is:

uint8_t c = (uint8_t)((int)(a) + (int)(b));

Apparently, it seems to be in the specification of C as said in this forum.

Additionally, in Visual Studio 2013, writing

auto c = a + b; 

And hovering the mouse pointer over c indicates that the type is int.

The questions are:

  • Why is the conversion needed, why is it in the spec? (If possible, with the answer, I'd like external sources of information to read more on the subject (such as MSDN, cppreference).)
  • How does that impact the performance?
like image 786
Vaillancourt Avatar asked Jan 05 '23 18:01

Vaillancourt


2 Answers

This is due to integral promotion rules. Specifically

Prvalues of small integral types (such as char) may be converted to prvalues of larger integral types (such as int). In particular, arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion, if applicable. This conversion always preserves the value.

like image 58
Cory Kramer Avatar answered Jan 14 '23 05:01

Cory Kramer


The questions are:

  • Why is the conversion needed, why is it in the spec? (If possible, with the answer, I'd like external sources of information to read more on the subject (such as MSDN, cppreference).)
  • How does that impact the performance?

Well,

  • The requirements for C++'s arithmetic operators to take integral operands can be found here:

  • The rules for Integral Promotions can be found here.

As to why its in the spec. Hypothetically... While CPUs may have instructions that can operate on 8bit integers, Within the CPU, writing/reading integers that are smaller than the width of the register may involve masking that you are unaware of.

Say you have a 32 bit register width. Adding two 8bits integer will usually require some masking to take the 8bit portions and pad the remaining 24bits with zeros... The ALU will do its work on the data in the registers and store the results in full register write (32bits). Then another masking to retrieve the results as an 8bit integer if you cast back..

So promoting it doesn't cost anything, because the CPU will do that anyway.

See: On 32-bit CPUs, is an 'integer' type more efficient than a 'short' type?.

Even your regular 32bit operations on 64bits

like image 36
WhiZTiM Avatar answered Jan 14 '23 04:01

WhiZTiM