为什么我需要从 `long &` 到 `int &` 的 reinterpret_cast,两者都是 32 位 (Windows LLP64)?

Why do I need reinterpret_cast from `long &` to `int &` where both are 32-bit (Windows LLP64)?

我在跨平台环境中使用 Qt。而我们 运行 陷入以下问题: 在 Windows 上,intlong int 都是 32 位整数;在 64 位 MacOS 和 Linux 上,int 是 32 位,long int 是 64 位(参见 https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)。

因此,跨平台库倾向于提供它们自己的固定位类型定义。在 Windows 上,Qt 将 quint32 定义为 unsigned int 并且不使用 unsigned long 整数。另一个库将其 Uint32 定义为 unsigned long。所以,两者实际上都是 32 位无符号整数,但具有不同的原始数据类型。

现在,碰巧我们尝试使用为 quint32 定义的 QDataStream 序列化和 Uint32 数据,令我们惊讶(或没有)的是,Visual C++ 抱怨QDataStream 运算符没有为 unsigned long 定义,这是真的,因为 Qt 使用几乎等价的 unsigned int 代替。

好的,解决方法是提供

#ifdef Q_OS_WIN
inline QDataStream & operator >> (QDataStream & stream, Uint32 & value)
{ return stream >> reinterpret_cast<quint32 &>(value); }

inline QDataStream & operator << (QDataStream & stream, Uint32 value)
{ return stream << quint32(value); }
#endif // def Q_OS_WIN

我的问题是:为什么我需要reinterpret_cast?我会觉得 static_cast 更舒服,因为据我所知,数据类型实际上是相同的。这里是龙?

intlong 是不同的数据类型,即使它们恰好在其他方面具有相同的属性。

您的 operator>> 由于严格的别名违规导致未定义的行为;编写代码的正确方法是:

inline QDataStream & operator >> (QDataStream & stream, Uint32 & value)
{ 
     quint32_t v;
     stream >> v;
     value = v;
     return stream;
}

(注意:我假设 QDataStream>> 与 C++11 istream>> 具有相同的 属性,因为它在读取失败时将值设置为 0;如果不是,则您需要包含一个分支,以便在读取失败时不执行 value = v;

您可以将 static_cast 用于 operator<<,因为它是一个值转换。事实上,您应该能够完全忽略 operator<<

您在问题中抱怨的问题是项目自行构建 typedef 而不是使用标准化类型的必然结果。不幸的是,在项目决定转向标准化类型之前,这只是您必须处理的事情。如果两者都使用 uint32_t 那么这个问题就不会存在了。