【问题标题】:Writing to a signed integer as if it is unsigned in C++写入一个有符号整数,就好像它在 C++ 中是无符号的一样
【发布时间】:2016-12-23 08:11:51
【问题描述】:

reinterpret_cast 这样做安全吗?这是最好的方法吗?

例如,在下面的代码中,我有一个名为ibytestream 的类,它允许从中读取uint16_ts 和int16_ts。 ibytestream::nextvector<unsigned char>::iterator

inline ibytestream& operator>>(ibytestream& stream, uint16_t& data) {
    data = 0;
    data |= *stream.next++;
    data <<= 8;
    data |= *stream.next++;
    return stream;
}

inline ibytestream& operator>>(ibytestream& stream, int16_t& data) {
    return stream >> reinterpret_cast<uint16_t&>(data);
}

我不想复制用于将字节转换为整数的代码,因此我使用reinterpret_cast 作为签名版本以重用未签名版本的代码。它在我的机器上运行良好,但在其他现代机器上也能正常运行吗?

【问题讨论】:

标签: c++ reinterpret-cast


【解决方案1】:

是的,这是安全的。

该标准的三个部分适用于做出此决定:

  1. 有符号和无符号类型的对齐要求相同
  2. 允许在指向具有相同对齐要求的类型的指针之间进行指针转换
  3. 执行泛左值之间的转换时,如果相应指针之间的转换有效,则该转换有效。

对于每个标准有符号整数类型,都存在一个对应的(但不同的)标准无符号整数类型:unsigned charunsigned short intunsigned intunsigned long int、 和unsigned long long int,它们各自占用相同的存储量,并具有相同的对齐要求。

对象指针可以显式转换为不同类型的对象指针。将“指向 T1 的指针”类型的纯右值转换为“指向 T2 的指针”类型(其中 T1 和 T2 是对象类型,并且 T2 的对齐要求不比 T1 的对齐要求更严格)并返回其原始类型会产生原始类型指针值。

如果可以使用 reinterpret_cast 将“指向 T1 的指针”类型的表达式显式转换为“指向 T2 的指针”类型,则可以将类型 T1 的泛左值表达式强制转换为类型“对 T2 的引用”。结果指 到与源 glvalue 相同的对象,但具有指定的类型。

【讨论】:

  • 我认为你错过了 M.M 在他的评论中提到的部分;您可以通过相应的无符号类型的表达式访问有符号整数对象。
【解决方案2】:

是的,应该没问题。 (在整数和字节数组之间移动存在潜在的字节序问题,但这是适用于有符号和无符号数字的另一回事。)

完全不同的东西:这一点:

data = 0;
data |= *stream.next++;

...可以简化:

data = *stream.next++;

【讨论】:

  • 我认为我的代码不会有字节序问题。无论底层机器的字节序如何,字节都将始终以大字节序读取。另外,我没有进行简化以使代码看起来一致(即data |= *stream.next++; 重复多行),我会假设我的编译器足够聪明,可以优化它。
  • 如果您需要跨架构的可移植性,这只是一个问题,而且您似乎不需要它。一切都好。
猜你喜欢
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-24
相关资源
最近更新 更多