C++ unsigned int 和 unsigned long int 之间的区别

yc2*_*986 4 c++ gcc g++ visual-studio

我正在 Windows 上使用 Visual Studio 编译器(特别是 Visual Studio 2015 Update 3)进行 C++ 开发。

对于一些 DSP 相关工作,我使用unsigned int / unsigned long数据类型。我想知道这两种内置 C/C++ 类型有什么区别。

我通过 Google 和 SO 进行了一些搜索,找到了这些参考资料。

  1. cppreference.com 上的类型文档
  2. MSDN 上的 Visual Studio 2015类型文档
  3. GNU C/C++ 的类型文档(由于G++ 编译器声明 C/C++ 使用相同的默认类型实现,我在这里参考 C 文档)

我假设 cppreference 文档是 ISO C++11 标准的摘要。因此,从“标准”来看,unsignedunsigned int是 16/32 位,具体取决于 LP/ILP 32/64 数据模型,而unsigned longunsigned long int是 32/64 位,具体取决于 LP/ILP 32/64 数据模型。

对于 MSDN 和 GNU 文档,他们都声明unsigned int / unsigned long使用 32 位实现,并且可以保存高达 4,294,967,295 的值。然而 GNU 文档还指出,根据您的系统,unsigned long 可能是 64 位,与 unsigned long long int 相同。

所以我的问题如下:

  1. 对于 unsigned long 64 位,超出上限 4,294,967,295 是未定义的行为还是正确的行为?
  2. 如果我有一个在 Visual Studio 中编译的 Windows 系统上运行的应用程序,基本上是unsigned == unsigned long。对或错?
  3. 如果我有一个由 GNU 编译器在 Linux/Windows 上编译的应用程序,我必须确保unsigned long == unsigned intunsigned long == unsigned long long以避免数据溢出。对或错
  4. 如果我有一个可能由所有这些 Visual Studio/GNU/Clang/Intel 编译器编译的跨平台应用程序,我必须使用一堆预处理器对环境进行明确分类,以避免数据溢出。对或错

提前致谢。

编辑: 感谢@PeterRuderman 指出,超出无符号类型的 ceil 值并不是未定义的行为。

那么我的问题1就会变成:

  1. 对于 unsigned long 64 位,超出上限 4,294,967,295 会导致自身回绕吗?

Pet*_*man 5

简短的回答是,是的,sizeof(unsigned)不能保证等于sizeof(unsigned long),但它确实在 MSVC 中。如果您需要以独立于平台的方式确定整数的大小,请使用<cstdint>:uint32_t和中的类型uint64_t。避免long在可移植代码中使用,它会导致很多麻烦。

另请注意,溢出符号整数并不是未定义的行为。定义的行为是值环绕。(例如std::numeric_limits< uint64_t >::max() + 43 == 42)。对于有符号类型来说,情况并非如此,其中溢出是未定义的行为。

为了回答您的最后一个问题,64 位整数可以存储 [0, 2 64 - 1] 范围内的值。2 32 + 1 不会导致环绕。

  • cstdint 中的类型是*相对*新的。委员会无法在不破坏大量代码的情况下删除旧类型。并且在某些情况下,出于性能原因,最好让编译器选择整数大小。 (2认同)