【问题标题】:On narrowing casts in C# between signed and unsigned integral types在 C# 中缩小有符号和无符号整数类型之间的强制转换
【发布时间】:2014-08-14 18:10:50
【问题描述】:

我试图确认一些关于缩小强制转换在 C#(5.0、.NET Framework 4.0/4.5)中使用整数类型的方式。底线:在有符号和无符号之间进行转换时,我能否确定整数类型的底层字节在顺序和值上都保持不变?

假设我做了以下事情:

short shortVal = -20000;
ushort ushortVal = (ushort)shortVal;

现在,我到目前为止所做的实验向我展示了以下两个字节数组中的字节:

byte[] shortBytes = BitConverter.GetBytes(shortVal);
byte[] ushortBytes = BitConverter.GetBytes(ushortVal); 

没有区别。我已经使用从shortushort 的显式缩小转换完成了这个精确的实验,shortVal 的值在Int16.MinValueInt16.MaxValue 的范围内。所有 2^16 个案例都可以正常检查。但是,实际解释的值自然会被重新解释,因为字节保持不变。我假设有符号整数类型使用二进制补码来表示有符号值(这是真的吗?)

我需要知道,我是否可以指望这些转换始终是“字节安全的”——例如不更改底层字节及其顺序。这也适用于从无符号到有符号的另一种转换。这些转换是否彼此完全相反?我主要关注 short/ushort 和 int/uint。但所有整数类型都值得关注。

这些细节可能取决于 C# 和 CLR 背后的技术的实现。我在这里严格关注适用于 Windows 32/64 位的 CLR。​​

【问题讨论】:

  • 是的。 C# 有符号整数类型使用二进制补码表示。

标签: c# casting type-conversion


【解决方案1】:

这可能相当棘手。

CLR 确实在 x86/x64 架构上使用二进制补码表示有符号整数(正如您在测试中观察到的那样),并且在不久的将来不太可能改变,因为架构本身对它有很好的支持。可以肯定的是,它会保持这种状态一段时间。

另一方面,我没有在 CLI 或 C# 规范中找到任何提及这一点,因此您一般不能指望它,尤其是在面对其他架构和/或 CLI 实现时。

所以这取决于你想用它做什么。如果可能的话,我会远离依赖于这样的实现细节,并使用更高级别的序列化工具来转换为任何二进制表示。

【讨论】:

  • 你知道 MODBUS 吗?较旧的从/主工业协议。我正在构建一些处理这个协议的软件。虽然我正在使用一个处理所有低级内容的库,但该库在其公共接口中使用short(因为 MODBUS 使用 16 位宽的寄存器)。我想看看在我的代码的更高级别上将short 的使用更改为ushort 是否会产生任何影响。似乎没有——目前。运行时检查可能很好,以防万一。
  • 我明白了,这实际上对您有好处 - 只要库负责二进制转换并公开 short,您应该可以安全地转换为 ushort(然后返回,未选中上下文),如果你不依赖其他地方的二进制表示。
猜你喜欢
  • 1970-01-01
  • 2016-10-01
  • 2013-04-06
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 2012-01-09
相关资源
最近更新 更多