【问题标题】:VS compilation warning: result of 32-bit shift implicitly converted to 64 bitsVS 编译警告:32 位移位结果隐式转换为 64 位
【发布时间】:2017-01-18 18:40:21
【问题描述】:

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 &lt;&lt; (PRECISION - 1 - i)改成1 &lt;&lt; (PRECISION - 1)似乎解决了。

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

显然,如果i &gt;= PRECISION,那么左移操作将产生未定义的行为。

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

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

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

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

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

谢谢

【问题讨论】:

    标签: c++ visual-studio compiler-warnings bit-shift


    【解决方案1】:

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

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

    强制它是 64 位移位。

    如果hiunint32_t,它也不会抱怨。

    【讨论】:

    • 那么为什么当我将PRECISION - 1 - i 更改为PRECISION - 1 时警告会清除(同时仍将结果存储在64 位变量中)???
    • @barakmanos 我的猜测和亚历克斯的一样。 1 &lt;&lt; PRECISION - 1 是一个编译时间常数,因此它可能被优化为 hi += constant
    • @NathanOliver 结果的存储与此警告无关,如果 hi 是 32 位,则原始错误将持续存在。此警告特定于 shift 操作本身(可能是 VS 特定的行为)
    【解决方案2】:

    编译器indeed suspects 表示 64 位:

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

    你可以考虑

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

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

    【讨论】:

    • 整数文字后缀 i64 是 Microsoft 扩展。当可移植性很重要时,最好使用ULLull
    • @FrançoisBeaune 我明白你的意思。但是ULL可能会超过64位,所以也不理想。我改成了uint64_t(1)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    相关资源
    最近更新 更多