【问题标题】:Get the largest signed integer type in C++获取 C++ 中最大的有符号整数类型
【发布时间】:2015-10-28 12:43:03
【问题描述】:

假设我必须接受一个大小作为处理数组的接口的参数。例如

void doSomethingRelatedToArrays(const size_t length)

在这里,我使用size_t 是出于以下考虑:

  • 长度必须始终为正数
  • size_t 总是类型定义为系统中最大的无符号整数类型。 std::size_t 可以存储理论上可能的任何类型对象的最大大小。

但是,我不应该在我的接口中使用无符号类型,因为客户端可以传入一个负数,该负数会隐式转换为无符号数,并且我无法在我的方法中验证它。请参阅 Scott Meyer 关于此主题的文章 here

所以,我应该将有符号整数类型传递给 API。但是我怎样才能得到系统中最大的有符号整数类型呢?是否有任何类似于size_t 的typedef 已签名?还是我应该改用size_t

【问题讨论】:

  • POSIX 有ssize_t
  • 注意:C 确实没有 定义“size_t 总是被类型定义为系统中最大的无符号整数类型”。 uintmax_t 是更好的候选“无符号整数类型,能够表示任何无符号整数类型的任何值”
  • std::make_signed_t<std::size_t>
  • Scott Meyer 文章,关于数组大小,很容易错误地使有效的大数组大小失败。尽管与不正确的负尺寸相比,这肯定不是一个常见的问题,但它只是将一个错误检测换成了另一个。如果参数是[INTMAX_MIN...INTMAX_MAX]中的整数,使用intmax_t,否则如果在[0...UINTMAX_MAX]范围内,使用uintmax_t,如果是FP,使用long double,如果是布尔值,使用@ 987654335@等
  • size_t 的签名对应物可能是ptrdiff_t,但它仍然不是最大的整数类型

标签: c++ c signed unsigned-integer size-t


【解决方案1】:

最近的 C 和 C++ 标准中最大的有符号整数类型是 long long。直到有比long long 更宽的类型之前,您始终可以使用它。如果你想要更多的未来证明,请使用intmax_t


size_t 始终被定义为系统中最大的无符号整数类型

这完全不正确!!! ❌

size_t 在 32 位系统中通常也是 32 位类型,这显然 不是可能的最宽类型。它只保证足以表示系统上最大对象的大小。在这种情况下,long long 显然要宽得多。在许多 16 位系统中,它只有 16 位,甚至与 long 的范围不同。


如果需要size_tptrdiff_t 可以用作签名对应方。但它也不是最大的类型。

对于比PTRDIFF_MAX 短的char 数组,std::ptrdiff_t 充当std::size_t 的签名对应物:它可以存储任何类型数组的大小,并且在大多数平台上与std::intptr_t 同义

http://en.cppreference.com/w/cpp/types/ptrdiff_t

在 C++20 中引入了 std::ssize,你猜怎么着,它还使用 ptrdiff_t 作为 size_t 的签名对应项

【讨论】:

    【解决方案2】:

    但是我怎样才能得到系统中最大的有符号整数类型呢?

    在 C++11 的 <cstdint> 中可以找到类型 intmax_t,它是在 C 标准 (7.20.1.5) 之后定义的:

    以下类型指定有符号整数类型,能够 表示任何有符号整数类型的任何值


    是否有任何类似于 size_t 的 typedef 已签名?

    不,不在 C++ 标准中。 POSIX 定义了ssize_t但是

    • 并不是要替换 size_t(它本身也受到 POSIX 的更多限制)
    • 并不意味着存储/传递负值,而是指示错误:

      ssize_t 应能够存储至少在 [-1, {SSIZE_MAX}] 范围内的值。


    所以,我应该将有符号整数类型传递给 API。 (...) 或者我应该 只用 size_t 代替?

    如果您的接口旨在处理 C++ 数组,size_t 是唯一一种由标准保证能够保存任何可能的数组索引的类型。使用任何其他类型,您可能(理论上)失去了处理所有数组的能力(甚至在您链接的文章中也提到了这一点)。

    因此,将size_t 用于索引目的是常见且习惯的 - 并且被许多库(包括 STL)使用。

    【讨论】:

    • ssize_t 不是 32 位 Linux 或 64 位 x32 ABI Linux 中最大的有符号整数类型
    【解决方案3】:

    使用的标准类型是std::intmax_t,它在<cstdint> 中定义。要获得最大值,您可以使用std::numeric_limits<intmax_t>::max()

    示例代码:

    #include <cstdint>
    #include <iostream>
    #include <limits>
    
    int main(int argc, char* argv[]) {
        std::cout << "max size = " << std::numeric_limits<intmax_t>::max() << std::endl;
    }
    

    【讨论】:

      【解决方案4】:

      size_t 的签名等价物只是 ssize_t,但这种类型在 C99 标准中没有定义,即使许多编译器都知道它。

      对于 C99 标准,最大有符号整数类型定义为 intmax_t

      参考:7. 库 / 7.18 整数类型 / 7.18.1.5 最大宽度整数类型

      【讨论】:

      • std::numeric_limits::max()、std::numeric_limits::is_signed 等
      • size_t 甚至不是最大的整数类型。在 16 位系统中可能只有 16 位,在 32 位系统中可能只有 32 位
      猜你喜欢
      • 2023-04-02
      • 2011-05-29
      • 2010-11-27
      • 1970-01-01
      • 2020-04-15
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多