【问题标题】:Byte swapping in bit wise operations逐位操作中的字节交换
【发布时间】:2015-01-28 22:50:51
【问题描述】:

我有一个我应该实现的称为字节交换的函数。这个想法是该函数采用 3 个整数(int x,int y,int z),该函数将交换 int x 的 y 和 z 字节。这些限制几乎仅限于按位操作(没有循环,也没有 if 语句或逻辑运算符,例如 ==)。

我认为我没有充分提出这个问题,所以我打算重新尝试

我现在明白了

byte 1 is referring to bits 0-7
byte 2 is referring to bits 8-15
byte 3                      16-23
byte 4                      24-31

我的函数应该接受 3 个整数输入,x、y 和 z。然后 x 上的 y 字节和 z 字节必须切换

int byteSwap(int x, int y, int z)

工作函数的ex

byteSwap(0x12345678, 1, 3) = 0x56341278
byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD

我的原始代码中有一些巨大的错误,即我认为一个字节是 2 位而不是 8 位。我正在努力解决的主要问题是我不知道如何访问这些位在给定字节内。例如,当我得到字节 4 和 5 时,我如何访问他们尊重的位?据我所知,我找不到给定字节与其起始位之间的数学关系。我假设我必须先转换然后屏蔽,然后将它们保存到变量中。尽管我什至无法做到这一点。

【问题讨论】:

  • 我不清楚它应该如何工作。如果您发布 1-2 个符合您标准的 x、y 和 z 示例,将会很有用。
  • = 运算符的左侧进行强制转换通常表明您做错了。
  • 添加了一些编辑来展示它应该如何工作的例子。希望现在一切都更清楚了,很抱歉造成混乱
  • 嗯,每个字节有 8 位,而不是 2。这个想法是从哪里来的?
  • @LeeDanielCrocker 不确定。感谢您指出这一点

标签: c


【解决方案1】:

使用((1ll << ((i + 1) * 8)) - 1) >> (i * 8) 提取第i 个字节。使用 XOR 运算符交换,并将交换的字节放在它们的位置。

int x, y, z;
y = 1, z = 3;
x = 0x12345678;

int a, b; /* bytes to swap */
a = (x & ((1ll << ((y + 1) * 8)) - 1)) >> (y * 8);
b = (x & ((1ll << ((z + 1) * 8)) - 1)) >> (z * 8);

/* swap */
a = a ^ b;
b = a ^ b;
a = a ^ b;

/* put zeros in bytes to swap */
x = x & (~((0xff << (y * 8))));
x = x & (~((0xff << (z * 8))));

/* put new bytes in place */
x = x | (a << (y * 8));
x = x | (b << (z * 8));

【讨论】:

    【解决方案2】:

    当您说 'x 的 y 和 z 字节'时,这意味着 x 是字节数组,而不是整数。如果是这样:

    x[z] ^= x[y];
    x[y] ^= x[z];
    x[z] ^= x[y];
    

    通过交换x[y]x[z] 来解决问题

    编辑后,您似乎想要交换 32 位整数的单个字节:

    在小端机器上:

    int
    swapbytes (int x, int y, int z)
    {
        char *b = (char *)&x;
        b[z] ^= b[y];
        b[y] ^= b[z];
        b[z] ^= b[y];
        return x;
    }
    

    在大端机器上:

    int
    swapbytes (int x, int y, int z)
    {
        char *b = (char *)&x;
        b[3-z] ^= b[3-y];
        b[3-y] ^= b[3-z];
        b[3-z] ^= b[3-y];
        return x;
    }
    

    通过对规则的严格解释,您甚至不需要异或技巧:

    int
    swapbytes (int x, int y, int z)
    {
        char *b = (char *)&x;
        char tmp = b[z];
        b[z] = b[y];
        b[y] = tmp;
        return x;
    }
    

    在大端机器上:

    int
    swapbytes (int x, int y, int z)
    {
        char *b = (char *)&x;
        char tmp = b[3-z];
        b[3-z] = b[3-y];
        b[3-y] = tmp;
        return x;
    }
    

    如果你想使用位移来实现(注意&lt;&lt;3 乘以 8):

    int
    swapbytes (unsigned int x, int y, int z)
    {
        unsigned int masky = 0xff << (y<<3);
        unsigned int maskz = 0xff << (z<<3);
        unsigned int origy = (x & masky) >> (y<<3);
        unsigned int origz = (x & maskz) >> (z<<3);
        return (x & ~masky & ~maskz) | (origz << (y<<3)) | (origy << (z<<3));
    }
    

    【讨论】:

    • X 应该是一个整数。我添加了一些编辑,希望能更清楚地说明,对于造成的混乱,我深表歉意
    • ...而且,亲爱的反对者,这里的问题究竟是什么?是的,这是人为的,但问题也是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 2015-03-21
    • 2014-04-12
    • 1970-01-01
    • 2020-05-22
    相关资源
    最近更新 更多