c函数根据字节顺序以特定顺序合并字节

c function to merge bytes in a specific order depended on endianness

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

例如:

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

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

现在我知道 char char *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

如有任何帮助,我们将不胜感激。

与字节顺序无关,你可以这样做。

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
}