It came to my attention that for simple operations on 8bit variables, the variables get converted to 32bit int
s 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:
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 asint
). 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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With