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

bar*_*nos 4 c++ bit-shift compiler-warnings visual-studio

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是编译警告:

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

这似乎改变时要解决1 << (PRECISION - 1 - i)1 << (PRECISION - 1)

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

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

但是,变量i不超过的值PRECISION - 1

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

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

但是,我到底该如何告诉编译器它永远不会做呢?

我发现了一个相关的问题,但没有提供适当的答案。

谢谢

Nat*_*ica 5

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

hi += 1ULL << (PRECISION - 1 - i);
Run Code Online (Sandbox Code Playgroud)

使其强制为64位移位。

如果hi是,它也不会抱怨unint32_t


Ale*_*exD 3

编译器确实怀疑64 位是指:

32 位移位的结果被隐式转换为 64 位,编译器怀疑 64 位移位是有意为之。要解决此警告,请使用 64 位移位,或将移位结果显式转换为 64 位。

您可以考虑

hi += uint64_t(1) << (PRECISION - 1 - i);
Run Code Online (Sandbox Code Playgroud)

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