将 char 移出范围的危险

Dangers of shifting a char out of scope

好的,

我编写了一个函数,从十六进制文件中获取一个无符号字符,然后将其向左移动以适合 WORD、DWORD 或 QWORD,如下所示:

retVal |= ((unsigned char)(memory[i]) << (8 * j));

(在循环内,因此变量 i 和 j)。

现在 visual studio 让我想起了可能的算术溢出。

我的问题:如果我将 j 限制为不超过 8(a uint64_t 的大小),我可以安全地忽略此消息吗? 我总是对警告感到有点沮丧,并试图消除它们。

根据我的理解,在保存值之前向左移动多少应该无关紧要,我错了吗?

编辑:

这是一个例子(这是我的函数):

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

您需要将 (8 * j) 限制为小于 sizeof(int) * CHAR_BIT 以保证您的代码在所有情况下都是合法的(假设是标准的 x86-64 实现)。

首先,当您执行 (unsigned char)(memory[i]) << (8 * j) 整数提升时,表达式的类型是提升左侧的类型。在这种情况下,如果 sizeof(unsigned char) < sizeof(int)unsigned char 被提升为 int,否则 unsigned int

然后[expr.shift]/1

The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.

这就是为什么 (8 * j) 需要小于 sizeof(promoted_type) * CHAR_BIT

的原因