1

好的,

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

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

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

现在视觉工作室让我想起了可能的算术溢出。

我的问题:如果我将 j 限制为不超过 8(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;
}
4

1 回答 1

4

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

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

然后[expr.shift]/1

如果右操作数为负数,或者大于或等于提升的左操作数的宽度,则行为未定义。

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

于 2020-01-27T21:41:45.150 回答