从一个给定的整数中提取两个有符号整数?

时间:2012-11-21 01:59:29

标签: c++ bit-manipulation

我有以下结构:

struct
{
   int a:4;
   int b:7;
   int c:21;
} example;

我想结合a和b在C ++中形成一个整数d。例如,我希望a的位值在b的位值的左边,以便形成整数d。这是如何在c ++中实现的?

示例:

a = 1001

b = 1010101

我想int d = 10011010101 xxxxxxxxxxxxxxxxxxxxx

其中x可以是先前属于d的21位。我希望a和b的值分别放在0-3和4-10位,因为占用前4位,b占结构“示例”中的后7位。

我感到困惑的部分是变量a和变量b都在最高位有一个“符号”位。这会影响结果吗?变量a和变量b中的所有位是否在整数d的最终结果中使用?整数d看起来像变量a的位和变量b的位串联吗?

由于

1 个答案:

答案 0 :(得分:2)

请注意,int位字段是有符号还是无符号是实现定义的。 C ++标准说明了这一点,C标准用不同的措辞实现了相同的净结果:

ISO / IEC 14882:2011 - C ++

  

§7.1.6.2简单类型说明符

     

¶3... [注意:实现定义char类型的对象和某些位域(9.6)是否为   表示为已签名或未签名的数量。 signed说明符强制char个对象和位字段   签;在其他情况下它是多余的。 - 后注]

     

§9.6比特字段

     

¶3...位域应具有整数或枚举类型(3.9.1)。它是   实现 - 定义是否是明文(既未明确签名也未签名)charshortintlong,   或long long位字段已签名或未签名。

ISO / IEC 9899:2011 - C

  

§6.7.2.1结构和联合说明符

     

¶10位字段被解释为具有由指定位数组成的有符号或无符号整数类型。 125)

     

125)如上面6.7.2中所述,如果使用的实际类型说明符是int或定义为int的typedef-name,那么它是实现定义的是否是位字段是否已签名或未签名。

     

§6.7.2类型说明符

     

¶5...对于位字段,它是实现定义的,指定符int是指定与signed int相同的类型还是指定与unsigned int相同的类型。

§6.7.2的上下文显示int可以与shortlong等结合使用,该规则将适用; C ++指定更清楚一点。当然,普通char的签名已经是实现定义的。


无符号位域

如果位字段的类型是无符号的,则表达式非常简单:

int d = (example.a << 7) | example.b;

有符号位字段

如果值已签名,那么您需要进行主要的解释练习,确定example.a为负数且example.b为正数时应该是什么值,反之亦然。在某种程度上,即使价值既是负面的,也是积极的,这个问题就会出现。

假设example.a = 7;example.b = 12; - d的价值应该是多少?可能同样的表达式适用,但你可以说最好减少1个位置:

assert(example.a >= 0 && example.b >= 0);
int d = (example.a << 6) | example.b;      // Alternative interpretation

其他案件由你决定;这取决于您想要对值进行的解释。例如:

int d = ((example.a & 0x0F) << 7) | (example.b & 0x7F);

这会强制将签名值视为无符号。它可能不是你想要的。


修改后的问题

example.a = 1001     // binary

example.b = 1010101  // binary

d = 10011010101 xxxxxxxxxxxxxxxxxxxxx
     

其中x可以是先前属于d的21位。

为此,您需要:

  d = (d & 0x001FFFFF) | ((((example.a & 0x0F) << 7) | (example.b & 0x7F)) << 21);

您可能可以使用更少的括号;我不确定我会冒这样做的风险。

联盟

但是,通过此修订后的规范,您很可能会想到union,例如:

union u
{
    struct
    {
       int a:4;
       int b:7;
       int c:21;
    } y;
    int x;
} example;

然而,位域中位的布局与int x;中的位没有指定(它们可能是最重要的位,也可能是最低位),并且总是有关于'如果您访问的联合中的值不是分配给您的最后一个,则调用未定义的行为'。因此,您需要处理位域的多个平台定义方面。事实上,这种难题通常意味着位字段与一种特定类型的机器(CPU)以及编译器和操作系统紧密相关。在你所追求的细节层面上,它们非常非常便携。