VS 编译警告:32 位移位的结果隐式转换为 64 位

VS compilation warning: result of 32-bit shift implicitly converted to 64 bits

Visual Studio 2013 发出恼人的(看似无关紧要的)编译警告:

#include <stdint.h>

#define PRECISION 16

uint64_t hi = 0;
for (uint8_t i = 0; i < PRECISION; i++)
{
    if (some_condition)
    {
        hi += 1 << (PRECISION - 1 - i);
    }
}

这里是编译警告:

warning C4334: '<<' :
result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)

1 << (PRECISION - 1 - i)改成1 << (PRECISION - 1)好像解决了。

所以我一直在试图找出 1 << (PRECISION - 1 - i) 中可能出现的问题。

显然,如果 i >= PRECISION,则左移操作会产生未定义的行为。

但是变量i没有超过PRECISION - 1的值。

此外,即使我们假设编译器无法推断出这一事实,我也看不出此编译警告与左移操作数导致的潜在未定义行为有什么关系。

可能假设PRECISION - 1 - i的无符号值可以大于31。

但是我应该如何准确地告诉编译器它永远不会呢?

我找到了 one related question,但没有提供正确的答案。

谢谢

64 位的编译器indeed suspects

The result of 32-bit shift was implicitly converted to 64-bits, and the compiler suspects that a 64-bit shift was intended. To resolve this warning, either use 64-bit shift, or explicitly cast the shift result to 64-bit.

你可以考虑

hi += uint64_t(1) << (PRECISION - 1 - i);

也许删除 i 可以抑制警告,因为编译器将表达式视为常量。

编译器抱怨是因为您将结果存储在 64 位变量中,因此它假设您实际上想要进行 64 位移位而不是 32 位移位。您可以使用

来解决这个问题
hi += 1ULL << (PRECISION - 1 - i);

强制转换为 64 位。

如果hiunint32_t它也不会报错。