stdint 类型与本机类型:long 与 int64_t、int32_t

stdint types vs native types: long vs int64_t, int32_t

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.

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

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

老实说,我完全不确定为什么 gcc 8.3 版本可以工作。如果 uint64_t 是 typedef'ed,代码应该可以在没有 write(long) 重载的情况下工作 也许是 gcc 8.3 中的错误?

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

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

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

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

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

how about equivalency of char, uint8_t, int8_t?

所有这些都是不同的类型。 std::uint8_t - 当它被定义时 - 是 unsigned char 的别名,而 std::int8_t - 当它被定义时 - 是 signed char 的别名。这两个都不同于 char 类型。