为什么“左移计数> =类型宽度”似乎很晚才开始?

问题描述 投票:0回答:1

对于上下文,我正在使用

g++ -std=gnu++23 -O3 -Wall
来编译我的代码(如果有什么区别的话)。我使用的是 64 位小端系统。

以下代码片段都显示了一些看似病态的行为:警告“左移计数>=类型宽度”的出现时间比我预期的要晚(部分解释见here),但似乎并没有像我那样进行完整的整数提升都会期望。

#include <cstdint>
#include <iostream>

int main()
{
  // any value will cause the confusing behaviour, of course
  uint8_t a = 5;
  a <<= 7;
  // 128, as expected
  std::cout << static_cast<int>(a) << '\n';

  uint8_t b = 5;
  b <<= 8;
  // 0, as expected, if slightly dubious (8 = width of type, right?)
  std::cout << static_cast<int>(b) << '\n';

  uint8_t c = 5;
  c <<= 16;
  // 0, as expected, assuming a promotion to a larger unsigned int type
  std::cout << static_cast<int>(c) << '\n';

  uint8_t d = 5;
  d <<= 31;
  // 0, as expected, assuming a promotion to a larger unsigned int type
  std::cout << static_cast<int>(d) << '\n';

  uint8_t e = 5;
  e <<= 64;
  /*
    raises a warning, rather understandably
    (I suppose it isn't aware of __uint128_t?)
  */
  // still outputs 0, although I assume this is undefined behaviour
  std::cout << static_cast<int>(e) << '\n';

  uint8_t f = 5;
  f <<= 32;
  /*
    raises a warning for some reason
    (shouldn't it just promote to uint64_t?)
  */
  // still outputs 0, although I assume this is undefined behaviour
  std::cout << static_cast<int>(f) << '\n';
}

发生什么事了?

c++ unsigned unsigned-integer integer-promotion
1个回答
0
投票

为什么“左移计数> =类型宽度”似乎很晚才开始?

它不“踢晚了”。当它缩进时,它会准确地踢出。

我想它不知道 __uint128_t?

__uint128_t
是编译器扩展。扩展不是标准整数促销的一部分。

不应该升级为uint64_t吗?

没有。

整数促销的规则是 https://en.cppreference.com/w/c/language/conversion#Integer_promotions 。这是,强调我的::

整数提升是对 rank 小于或等于 int 的rank 的任何整数类型值或 _Bool(until C23)bool(since C23)、int、signed int、unsigned 类型的位字段的隐式转换int,为 int 或 unsigned int 类型的值

假设正常系统,

uint8_t
unsigned char
。晋升为
unsigned int
。您系统上的
unsigned int
宽度为 32 位。

© www.soinside.com 2019 - 2024. All rights reserved.