【问题标题】:Change the width of a signed integer to a nonstandard width将有符号整数的宽度更改为非标准宽度
【发布时间】:2015-04-29 09:11:09
【问题描述】:

对于网络应用程序,我需要一个带符号的 2 的补码整数。具有自定义宽度。在运行时指定。假设整数的值落在宽度内。

我遇到的问题是奇偶校验位。有什么方法可以避免手动设置奇偶校验位?假设我有一个宽度为 11 位的整数,我会将其存储在 2 个字符的数组中,如下所示:

int myIntWidth = 11;
int32_t myInt= 5;
unsigned char charArray[2] = memcpy(charArray, &myInt, (myIntWidth + 7)/8);

【问题讨论】:

  • 使用位域来获得所需的整数大小。可能您会希望将此位字段与联合中的简单整数(如果联合大于整数)结合起来,以获得对简单修改的​​简单访问。
  • 位字段本质上是不可移植的。对于网络应用程序,您需要存储另一端的服务器或设备期望的值,而不是您的编译器认为正确的值。
  • 使用位域的一个问题是它的大小不能在运行时定义。
  • @Lưu Vĩnh Phúc 这与我想要实现的目标相反。我正在尝试减小 int 宽度。

标签: c++ memory integer signed signed-integer


【解决方案1】:

它不是那样工作的。它不起作用,因为您从 myInt 的开头复制两个字节,但您不知道您感兴趣的字节存储在哪里。您还需要知道存储字节的顺序。根据这一点,使用以下两个代码之一:

unsigned char charArray [2];
charArray [0] = myInt & 0xff; // Lowest 8 bits
charArray [1] = (myInt >> 8) & 0x07; // Next 3 bits

unsigned char charArray [2];
charArray [1] = myInt & 0xff; // Lowest 8 bits
charArray [0] = (myInt >> 8) & 0x07; // Next 3 bits

【讨论】:

  • 你的意思是,“你不知道你想要的字节存储在哪里”。在 little endian 上,11 个最低有效位将是前两个,对吧? 0xff 的问题在于,它仅适用于 8 位,我希望它也适用于 11 和 8 等数字,这些数字将在运行时确定。我想这需要一个查找表。
  • 有一个标准技巧可以为低 N 位制作掩码:(1u << N) - 1。 (N 必须小于您正在使用的类型的宽度,当然)或者,对所有 1 的掩码应用右移,例如0xff >> (8 - N)。对于0 < N <= 8
【解决方案2】:

在上面很多帖子的帮助下,我想出了这个解决方案:

inline void reduceSignedIntWidth(int32_t& destInt, int width)
{
    //create a value mask, with 1's at the masked part
    uint32_t l_mask = (0x01u << width) - 1;

    destInt &= l_mask;
}

它将返回减少的 int,以零作为填充。

【讨论】:

  • for 循环的意义何在? l_mask = (l_mask &lt;&lt; 1) &amp; 0x01;的结果不总是0吗?您将 0x01 向左移动 1 位,结果为 0x02。 0x01 & 0x02 = 0x00。还是我错过了什么? :)
  • 谢谢@rozina,确实应该是l_mask = (l_mask &lt;&lt; 1) | 0x01; 但是,我已将其更改为@Hurkyl 建议的方式。我认为这是一个非常漂亮的技巧:)
猜你喜欢
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多