2

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

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

现在,碰巧的是,我们尝试使用为数据QDataStream定义的序列化,令我们惊讶的是(或没有),Visual C++ 抱怨没有为它定义的操作符是真的,因为 Qt 使用了几乎等价的代替。quint32Uint32QDataStreamunsigned longunsigned 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是,据我所知,数据类型实际上是相同的。这里有龙?

4

1 回答 1

2

int并且long是不同的数据类型,即使它们碰巧具有相同的属性。

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_castfor,operator<<因为它是一种价值转换。事实上,你应该可以operator<<完全忽略它。

您在问题中感叹的问题是项目组成自己的类型定义而不是使用标准化的类型定义的必然结果。不幸的是,在项目决定转向标准化类型之前,这只是您必须处理的事情。如果两者都使用了,uint32_t那么这个问题就不存在了。

于 2017-11-16T22:36:47.737 回答