代码之家  ›  专栏  ›  技术社区  ›  Martijn Courteaux

C++与联合运算

  •  4
  • Martijn Courteaux  · 技术社区  · 16 年前

    我有两个 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 ...
    (但是: c1 c2级 在我的真实应用程序中是负数。。。也许这是问题的一部分?)

    所以,我的第二个解决方案是使用 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) 最好/最快的方法是什么?

    5 回复  |  直到 13 年前
        1
  •  7
  •   Potatoswatter    12 年前

    这个 union si 取决于平台的端部)。

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

    1111 1011
    

    int 甚至 unsigned int ,它变成

    1111 1111 1111 … 1111 1011
    

    当OR被应用时,所有这些1会淹没左移的数据。

    char s到 unsigned char 然后到 内景

    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;
    }
    
        2
  •  3
  •   Chubsdad    16 年前

    所以尝试将c1类型转换为无符号int,然后用C2按位或。还返回输出为无符号int。字符提升为int,但我们希望为“unsigned int”

        3
  •  2
  •   Johannes Schaub - litb    16 年前

    原因是 c2 int 在执行按位“或”之前,它会导致符号扩展(假设char是有符号的,并且可以包含负值):

    char x1 = -2; // 1111 1110
    char x2 = -3; // 1111 1101
    
    short int si = stitch(c1, c2); // 1111 1111 1111 1101
    

    代表 x2 晋升为 内景 1 ,因此它将覆盖 x1 你以前调职的。你可以投给 unsigned char 第一。对于双补码表示,这不会改变最低字节中的位模式。虽然不是绝对必要的,但你可以 c1 无符号字符 同样,为了保持一致性(如果short是2字节长,那么这并不重要) c1类

    short int stitch(char c1, char c2) {
        return ((unsigned char)c1 << 8) | (unsigned char)c2;
    }
    
        4
  •  1
  •   jilles    16 年前

    shift/or方法一旦修复,就更干净了,因为它不依赖于字节顺序。

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

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

        5
  •  -1
  •   adf88    16 年前

    //编辑 上面的“联合规则”有一个例外,你可以同时使用前面的这些成员,它们的布局相同。即

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

    A.c和A.i可与B.c和B.i同时使用