繁体   English   中英

C ++:Union vs Bitwise运算符

[英]C++: Union vs Bitwise operators

我有两个char ,我想把它们“按”拼接在一起。
例如:

char c1 = 11; // 0000 1011
char c2 = 5;  // 0000 0101
short int si = stitch(c1, c2); // 0000 1011 0000 0101

所以,我首先尝试的是按位运算符:

short int stitch(char c1, char c2)
{
    return (c1 << 8) | c2;
}

但这不起作用:我得到一个short等于c2 ...... (1)为什么?
(但是: c1c2在我的真实应用程序中是负数...也许这是问题的一部分?)

所以,我的第二个解决方案是使用union

union stUnion
{
    struct
    {
         char c1;
         char c2;
    }
    short int si;
}

short int stitch(char c1, char c2)
{
    stUnion u;
    u.c1 = c1;
    u.c2 = c2;
    return u.si;
}

这就像我想要的...... 我想

(2)什么是最好/最快的方式?

谢谢!

union方法最多是实现定义的(实际上,它将非常可靠地工作,但si的格式取决于平台的字节顺序)。

正如您所怀疑的那样,按位方式的问题是负数。 负数由前导1的链表示。 所以-5例如是

1111 1011

如果将其转换为int或甚至unsigned int ,它就会变为

1111 1111 1111 … 1111 1011

当应用OR时,所有那些1将淹没左移数据。

要解决这个问题,请将charunsigned char ,然后转换为int (以防止溢出,甚至出现溢出的可能性):

short int stitch(char c1, char c2)
{
    return ( (int) (unsigned char) c1 << 8) | (unsigned char) c2;
}

或者,如果您可以自由更改参数的类型,并且可以包含<cstdint>

uint16_t stitch( uint8_t c1, uint8_t c2)
{
    return ( (int) c1 << 8 ) | c2;
}

$ 5.8 / 1状态 - “操作数应为整数或枚举类型,并执行整数提升。结果的类型是提升左操作数的类型。如果右操作数为负,或者等于或等于,则行为未定义以升级的左操作数的位数为长度。“

因此,尝试将c1类型转换为unsigned int,然后对C2进行按位OR运算。 还将输出作为unsigned int返回。 chars被提升为int但我们希望成为'unsigned int'

原因是在执行按位OR之前首先将c2提升为int ,这会导致符号扩展(假设char已签名且可以保存负值):

char x1 = -2; // 1111 1110
char x2 = -3; // 1111 1101

short int si = stitch(c1, c2); // 1111 1111 1111 1101

提升为intx2的表示是(至少)1字节满1 ,因此它会覆盖先前向上移位的x1的零位。 您可以先转换为unsigned char 使用两个补码表示,不会更改最低字节中的位模式。 虽然不是绝对必要,但为了保持一致性,你也可以将c1unsigned char (如果short是2个字节长,那么c1符号扩展超出这2个字节并不重要)

short int stitch(char c1, char c2) {
    return ((unsigned char)c1 << 8) | (unsigned char)c2;
}

移位/或方法一旦修复,就更清晰,因为它不依赖于字节排序。

除此之外,由于存储到负载转发(STLF)问题,许多现代CPU上的union方法可能会更慢。 您正在将值写入内存,然后将其作为不同的数据类型读回。 如果发生这种情况,许多CPU无法快速将数据发送到负载。 负载需要等到存储完全完成(退役),将其数据写入L1缓存。

在没有桶形移位器的非常旧的CPU(移位8需要8次操作)和简单的有序执行(例如68000)上,union方法可能更快。

你不应该使用联盟。 你永远不应该同时使用联合字段。 如果工会有成员A和成员B,那么你必须考虑A和B是无关的。 那是因为编译器可以随意在任何地方添加填充(除了在struct的前面)。 另一个问题是字节顺序(小/大端)。

//编辑上面的“联合规则”有例外,您可以同时使用这些成员,这些成员位于前端并具有相同的布局。

union {
    struct {
        char c;
        int i;
        short s;
    } A;
    struct {
        char c;
        int i;
        char c1;
        char c2;
    } B;
};

Ac和Ai可与Bc和Bi同时使用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM