Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C/C++, what's the minimum type up-casting required for mixed-type integer math?

Tags:

c++

I have code that depends on data that is a mixture of uint16_t, int32_t / uint32_t and int64_t values. It also includes some larger bit shifted constants (e.g., 1<<23, even 1<<33).

In calculation of a int64_t value, if I carefully cast each sub-part (e.g., up-casting uint16_t values to int64_t) it works - if I don't, the calculations often go awry.

I end up with code that looks like this:

int64_t sensDT = (int64_t)sensD2-(int64_t)promV[PROM_C5]*(int64_t)(1<<8);
temperatureC = (double)((2000+sensDT*(int64_t)promV[PROM_C6]/(1<<23))/100.0);

I wonder, though, if my sprinkling of type casts here is too cluttered and too generous. I'm not sure the 1<<8 requires the cast (while despite not having one, 1<<23 doesn't lead to erroneous calculations) but perhaps they do too. How much is too much when it comes to up-casting values for a calculation like this?

Edit: So it's clear, I'm asking what the minimum proper amount of casting is - what's necessary for correct functionality (one can add more casts or modifiers for clarity, but from the compiler's perspective what's necessary to ensure correct calculations?)

Edit2: I'm using C-style casts as this is from an Arduino-type embedded code base (which itself used that style of casts already). From the perspective of having the desired effect they appear to be equivalent, thus I used the existing coding style.

like image 203
MartyMacGyver Avatar asked Jun 23 '16 15:06

MartyMacGyver


1 Answers

Generally you can rely on the integer promotions to give you the correct operation, as long as one of the operands for each operator have the correct size. So your first example could be simplified:

int64_t sensDT = sensD2-(int64_t)promV[PROM_C5]*(1<<8);

Be careful to consider the precedence rules to know what order the operators will be applied!

You might run into trouble if you're mixing signed and unsigned types of the same size, although either should promote to a larger signed type.

You need to be careful with constants, because without any decoration those will be the default integer size and signed. 1<<8 won't be a problem, but 1<<35 probably will; you need 1LL<<35.

When in doubt, a few extra casts or parentheses won't hurt.

like image 115
Mark Ransom Avatar answered Nov 01 '22 22:11

Mark Ransom