Okay,
I wrote a function that takes an unsigned char from a hex file and then shifts it to the left to fit inside a WORD,DWORD or QWORD, like follows:
retVal |= ((unsigned char)(memory[i]) << (8 * j));
(inside a loop, hence variables i and j).
Now visual studio reminds me of possible arithmetik overflow.
My question: If I limit j to be never more than 8 (size of a uint64_t), can I safely ignore this message? I am always a little bummed about warnings and try to eliminate them.
In my understanding it should not matter how much you shift to the left before saving the value, am I mistaken?
EDIT:
here is an example (it's my function):
int getValuePNTR(const char* memory, int &start, int size)
{
uint64_t retVal = 0;
//now just add up array fields
for (int i = start + size-1,j = size-1; j >= 0; --j, i--)
{
//fprintf(stdout, "\ncycle: %d, memory: [%x]", j, memory[i]);
if ((unsigned char)memory[i] == 00 && j > 0)
retVal <<= 8;
else
retVal |= ((unsigned char)(memory[i]) << (8 * j));
}
//get the next field after this one
start += size;
return retVal;
}
You need to limit (8 * j)
to be less than sizeof(int) * CHAR_BIT
in order to keep you code legal in all cases (assuming a standard x86-64 implementation).
First, when you do (unsigned char)(memory[i]) << (8 * j)
integer promotion happens and then type of the expression is the type of the promoted left hand side. In this case unsigned char
is promoted to int
if sizeof(unsigned char) < sizeof(int)
and unsigned int
otherwise.
Then [expr.shift]/1 has
The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.
Which is the reason why (8 * j)
needs to be less than sizeof(promoted_type) * CHAR_BIT