I am working on a program that mixes 64 bit (for some calculations) and 32 bit (for space saving storage) unsigned integers, so it is very important I keep them sorted out during arithmetic to avoid overflows
Here’s an example problem
I want to bit shift 1 to the left by an unsigned long n, but I want the result to be an unsigned long long. This will be used in an comparison operation in an if statement, so there is no assignment going on. I’ll give you some code.
void example(unsigned long shift, unsigned long long compare)
{
if((1<<shift)>compare)
{
do_stuff;
}
}
I suspect that this would NOT do what I want, so would the following do what I want?
void example(unsigned long shift, unsigned long long compare)
{
if(((unsigned long long)1<<shift)>compare)
{
do_stuff;
}
}
How do I micromanage the bit width of these things? Which operand determines the bit width that the operation is performed with, or is it the larger of the two?
Also, I would like a run down of how this works for other operations too if possible, such as + * / % etc.
Perhaps a reference to a resource with this information would be good, I cannot seem to find a clear statement of this information anywhere. Or perhaps the rules are simple enough to just post. I am not sure.
For the bit-shifts, it’s the left operand (the one to be shifted) that determines the type that the operation is performed with. If the integer promotions convert it to
intorunsigned int, the operation is performed at that type, otherwise at the type of the left operand.For the comparison, the result of the shift may then be converted to the type of the other operand. In your example code, the integer constant
1has typeint, hence the shift would be performed at typeint, and the result of that converted tounsigned long longfor the comparison. Casting works, since the result has a type that is not changed by the integer promotions, as would using a suffixed literal1ull.For the other listed operations, the arithmetic operations (as for comparisons), the type at which the operation is performed is determined by both operands as follows: