【问题标题】:stdint types vs native types: long vs int64_t, int32_tstdint 类型 vs 本机类型:long vs int64_t, int32_t
【发布时间】:2021-08-24 02:17:36
【问题描述】:

uint64_t、uint32_t、long 和 int(即 stdint 和本机编译器类型)的类型等效性是否发生了变化。还是我遇到了 g++ 错误?

g++ 8.3 中带有 c++17 选项的以下代码编译没有错误。架构是 arm 32 位。

std::stringstream os;

void write(long value)
{
    os << value;
}
void write(int64_t value)  // G++ 9.4 error: indistinguishable overload.
{
    os << value;
}
void write(int32_t value)
{
    os << value;
}

long value = 1;
write(longValue);  // g++ 8.3: no matching overload, if the write(long) overload is removed.

使用 g++ 9.4 和 c++17 选项编译的相同代码会出错,因为 long 和 in64_t 重载无法区分。 (我所期望的)。

但是删除 write(long) 重载会导致 g++ 8.3 抱怨没有匹配的重载。 (不是我在任何版本的 C++ 标准中所期望的)。

老实说,我不知道为什么 gcc 8.3 版本可以正常工作。如果 uint64_t 是 typedef 的,那么代码应该可以在没有 write(long) 重载的情况下工作,也许是 gcc 8.3 中的一个错误?

当我们在这里的时候:char、uint8_t、int8_t 的等价性如何? (如果它们是不同的,那将是一件好事)。我似乎确实记得 wchar_t 成为与 C++ 中的 uint16_t/int16_t 不同的类型(mumble-mumble)。其他的不清楚。

【问题讨论】:

  • 当您使用 g++ 9.4 编译时,您是否还针对 ARM32 还是 64 位目标?
  • 好问题。 g++ 9.4 目标是 AMD64。
  • 那就是原因。 long 在非 Windows 中在 64 位操作系统上是 64 位,在 32 位操作系统上是 32 位。
  • 好的。那么为什么 int32_t 重载在 ARM 32 位上没有冲突呢?
  • int32_t 很可能是 int 的 typedef,并且由于 long 的排名高于 int,因此它不会转换为它。

标签: c++ g++


【解决方案1】:

是的,不同的 CPU 架构具有不同大小的基本类型,固定宽度的别名映射到不同的类型。这也因操作系统而异;不仅仅是建筑。这是正常的,不是错误,通常不会在编译器版本之间发生变化。

为避免这个问题,要么只为固定宽度类型提供重载,要么为每个基本类型提供重载。不要混合它们。

在这种情况下,使用函数模板而不是重载可能会更好:

template<class T>
void write(T value)
{
    os << value;
}

char、uint8_t、int8_t 的等价性如何?

所有这些都是不同的类型。 std::uint8_t - 完全定义时 - 是 unsigned char 的别名,std::int8_t - 定义时 - 是 signed char 的别名。这两者都不同于char 类型。

【讨论】:

  • 被推荐为非常好的建议,尽管它没有解决为什么的问题。实际的问题是我完全无法想象 long 是 32 位的架构(例如 ARM32 LINUX)。 :-/
  • @RobinDavies I had completely failed to imagine an architecture in which long was 32 bits 另一个相当流行的 32 位系统是 windows(x86 和 x86-64)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
  • 2014-09-20
  • 2014-05-25
  • 1970-01-01
相关资源
最近更新 更多