将两个短裤组合成int的最简洁方法

dew*_*rde 7 c++

我有两个16位短路(s1和s2),我试图将它们组合成一个32位整数(i1).根据我正在处理的规范,s1是最重要的单词,而s2是最不重要的单词,并且组合单词似乎是签名的.(即s1的最高位是符号.)

结合s1和s2最简洁的方法是什么?

我想到了类似的东西

const utils::int32 i1 = ((s1<<16) | (s2));
Run Code Online (Sandbox Code Playgroud)

会这样做,而且似乎有效,但我担心左移16分.

另外,我对使用工会来完成这项工作的想法很感兴趣,是否有任何关于这是好事还是坏事的想法?

小智 13

你所做的只有在short和int都是无符号的情况下才有意义.如果其中一个短路是有符号且具有负值,那么将它们组合成单个int的想法是没有意义的,除非您已经提供了特定于域的规范来涵盖这种可能性.


Mar*_*som 6

你所拥有的看起来几乎是正确的,但如果第二部分是否定的话可能会失败; 隐式转换为int可能会签名扩展并用1填充高16位.对无符号短路的转换可能会阻止这种情况发生,但最好的方法是屏蔽掉这些位.

const utils::int32 combineddata = ((data.first<<16) | ((data.second) & 0xffff));
Run Code Online (Sandbox Code Playgroud)


Lun*_*din 5

我知道这是旧帖子,但是当前发布答案的质量令人沮丧。

这些是要考虑的问题:

  • 短裤(或其他小整数类型)的隐式整数提升将导致带int符号类型的操作数。无论小整数类型的有符号性如何,都会发生这种情况。整数提升发生在移位运算和按位或运算中。
  • 对于移位运算符,结果类型是提升后的左操作数的类型。在按位或的情况下,从“常规算术转换”获得结果类型。
  • 左移负数会导致不确定的行为。右移负数会导致实现定义的行为(逻辑移位与算术移位)。因此,在所有用例的99%中,不应将带符号的数字与位移一起使用。
  • 联合,数组和类似方法不是很理想的解决方案,因为它们使代码的依赖性取决于代码。此外,在C ++中,通过联合进行类型修剪也不是明确定义的行为(与C不同)。基于指针的解决方案很糟糕,因为它们最终将违反“严格的别名规则”。

因此,适当的解决方案将是:

  • 使用保证类型为无符号且不会隐式提升的操作数。
  • 使用移位,因为这些移位与时延无关。
  • 不要将某些非便携式的hogwash解决方案与联合或指针一起使用。除了不可移植性之外,此类解决方案绝对没有任何收获。但是,此类解决方案可能会引发一种或几种未定义行为的情况。

它看起来像这样:

int32_t  i32 = (int32_t)( (uint32_t)s1<<16 | (uint32_t)s2 );
Run Code Online (Sandbox Code Playgroud)

任何其他解决方案都是高度可疑的,充其量是不可移植的。


twk*_*twk 1

尝试将 data.second excile 投影为短类型,例如:

const utils::int32 combineddata = ((data.first<<16) | ((short)data.second));
Run Code Online (Sandbox Code Playgroud)

编辑:我是 C# 开发人员,可能您的代码语言中的转换看起来不同,但想法可能是相同的。