c++byte-shifting

Dangers of shifting a char out of scope


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;
}

Solution

  • 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