首页 > 解决方案 > -9'223'372'036'854'775'808LL 无符号

问题描述

由于 C++20 二进制补码表示是标准允许的唯一表示,保证范围从 -2 N-1到 +2 N-1 -1。因此,对于 64 位有符号整数类型,范围从-9'223'372'036'854'775'8089'223'372'036'854'775'807。但是,此代码不能在 Visual Studio 上编译(也不能在 gcc 上编译)

int main()
{
    long long x{-9'223'372'036'854'775'808LL};
    // error C4146: unary minus operator applied to unsigned type, result still unsigned
    // error C2397: conversion from 'unsigned __int64' to '__int64' requires a narrowing conversion
}

然而,如果我用 compiles 替换代码long long x{-9'223'372'036'854'775'807LL - 1}就好了并且x保持正确的值。我没有得到什么?

标签: c++integerliteralsc++20long-long

解决方案


如果没有LL后缀,则该类型将被视为符合标准的列表中的第一个类型。如果您使用LL后缀,则该值将特别具有 type long long。然而,任何一种方式9'223'372'036'854'775'808都太大而无法适应 along long(这是最大的有符号类型),因此一些编译器允许它作为扩展成为unsigned long long,因此会发出警告。在这种情况下, GCC 和 Clang实际上会发出警告。与许多人的看法相反,C 或 C++ 中没有负整数文字-9'223'372'036'854'775'808是应用于整数的一元减号9'223'372'036'854'775'808

字面量的类型

整数文字的类型是值可以适合的第一种类型,来自类型列表,这取决于使用了哪个数字基数和哪个整数后缀

  • 无后缀
  • 十进制基数:
    • 整数
    • 长整数
    • long long int (C++11 起)
  • 二进制、八进制或十六进制基数:
    • 整数
    • 无符号整数
    • 长整数
    • 无符号长整数
    • long long int (C++11 起)
    • unsigned long long int (C++11 起)
  • ...
  • 后缀:ll 或 LL
  • 十进制基数:
    • long long int (C++11 起)
  • 二进制、八进制或十六进制基数
    • 长长整数
    • unsigned long long int (C++11 起)
  • ...

如果整数字面量的值太大而无法容纳后缀/基数组合所允许的任何类型,并且编译器支持扩展整数类型(例如__int128),则可以给字面量赋予扩展整数类型——否则程序会出错-形成。

事实上,过去有很多类似的问题 where-2147483648也是 unsigned因为long long当时不在 C 和 C++ 标准中,最大的类型是unsigned long


推荐阅读