繁体   English   中英

位移导致奇怪的类型转换

[英]Bit shift leads to strange type conversion

以下代码在没有警告的情况下编译:

std::uint16_t a = 12;
std::uint16_t b = a & 0x003f;

但是,与按位一起执行位移并导致“隐式强制警告”:

std::uint16_t b = (a & 0x003f) << 10; // Warning generated.

gcc和clang都抱怨存在从intuint16_t的隐式转换,但我不明白为什么引入位移会导致右手表达式突然计算为int

编辑:对于clang,我使用-std=c++14 -Weverything标志进行编译; 对于gcc,我使用-std=c++14 -Wall -Wconversion标志编译。

使用整数类型执行任何算术总是在促销之前至少(有时,但在这种情况下不使用gcc, unsignedint 正如您在此示例中所看到的,这首先适用于您,也适用于无警告变体。

解决这些(通常是令人惊讶的)整数提升规则的最好方法是在get go中使用unsigned int (或常见平台上的uint32_t )。

如果你不能或不想使用更大的类型,你可以将整个表达式的static_cast回到std::uint16_t

std::uint16_t b = static_cast<std::uint16_t>((a & 0x003f) << 10); 

这将正确地导致RHS值mod 2 ^ 16。

但我没有看到为什么引入位移会导致右手表达式突然计算为int。

我想你误解了这个警告。 在这两种情况下,表达式求值为int但在第一种情况下,结果总是适合uint16_t ,在第二种情况下,它不会。 看起来编译器足够智能以检测它并仅在第二种情况下生成警告。

来自cppreference.com“如果传递给算术运算符的操作数是整数或无范围枚举类型,那么在任何其他操作之前(但在左值到右值转换之后,如果适用),操作数将进行整数提升 。”

例如:

byte a = 1;
byte b = a << byte(1);
  1. a1被提升为intint(a)int(byte(1))
  2. a向左移动一个位置: int result = int(a) << int(byte(1)) (结果为int )。
  3. result存储在b 由于intbyte宽,因此将发出警告。

如果操作数是常量表达式 ,则编译器可能能够在编译时计算结果,并在结果不适合目标时发出警告:

byte b = 1 << 1; // no warning: does not exceed 8 bits
byte b = 1 << 8; // warning: exceeds 8 bits

或者,使用constexpr

constexpr byte a = 1;
byte b = a << 1; // no warning: it fits in 8 bits
byte b = a << 8; // warning: it does not fit in 8 bits

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM