0

我希望能够合并来自两个无符号长参数的字节,正好占字节的一半,从第二个参数的最低有效字节开始的一半和第一个参数的其余部分。

例如:

x = 0x89ABCDEF12893456 
y = 0x76543210ABCDEF19
result_merged = 0x89ABCDEFABCDEF19

首先,我需要检查我工作的系统是小端还是大端。我已经写了一个函数来检查它,叫做is_big_endian()

现在我知道 charchar *c = (char*) &y会给我存储在最大内存地址的字节。

现在,我想使用 AND(&) 位运算符来合并 x 和 y 字节,但我不能使用它,因为我真的不知道“long”的大小是多少,32 或 64 可能不同位系统,所以我不能真正使用固定大小。

这意味着我不能使用任何位掩码,例如:

(y & 0x00000000ffffffff) | (x & 0xffffffff00000000);

我不允许使用 long long、uint_fast64_t 或 reinterpret_cast 或任何其他“外部”的东西。

我在想:

  1. 使用字节移位
  2. 使用一个数组来存储位并在这个数组上运行一个循环。

所以我写了这段代码,我可以只使用“sizeof”来查找 long 的大小,而不关心它是 32 位还是 64 位系统。

unsigned long merge(unsigned long x, unsigned long int y)
        {
        char* charX = (char*)&x;
        char* charY = (char*)&y;
        if (is_big_endian == 0){
    // it's a little endian machine
            for (int i=0; i<(sizeof(unsigned long))/2; i++){
                *charX<<1;
                *charY>>1;
            }
        }
        else
                {
                    for (int i=0; i<(sizeof(unsigned long))/2; i++){
                    *charX>>1;
                    *charY<<1;
                }
            }
            return (x | y);
        }

如果那是一个小端系统,我已经把 y 的右边位去掉了,因为那里的 LSB 是最左边的位。如果这是一个大端系统,则相反。

但它运行得不太好,输出是:0xffffffffbbcdff5f

任何帮助,将不胜感激。

4

1 回答 1

2

字节顺序无关紧要,您可以这样做。

unsigned long merge(unsigned long x, unsigned long y)
{
    if(sizeof x == 4)
        return (x & 0xFFFF0000ul) | (y & 0x0000FFFFul);
    else
        return (x & 0xFFFFFFFF00000000ul) | (y & 0x00000000FFFFFFFFul);
}

也可以使用条件编译

unsigned long merge(unsigned long x, unsigned long y)
{
#if ULONG_MAX == 0xFFFFFFFFul
    return (x & 0xFFFF0000ul) | (y & 0x0000FFFFul);
#else
    return (x & 0xFFFFFFFF00000000ul) | (y & 0x00000000FFFFFFFFul);
#endif
}
于 2020-11-20T19:46:52.653 回答