C++中的整数字节交换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3916097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:03:27  来源:igfitidea点击:

Integer Byte Swapping in C++

c++bytebit-manipulation

提问by Rob S.

I'm working on a homework assignment for my C++ class. The question I am working on reads as follows:

我正在为我的 C++ 课做家庭作业。我正在研究的问题如下:

Write a function that takes an unsigned short int (2 bytes) and swaps the bytes. For example, if the x = 258 ( 00000001 00000010 ) after the swap, x will be 513 ( 00000010 00000001 ).

编写一个函数,它接受一个 unsigned short int(2 个字节)并交换字节。例如,如果交换后 x = 258 ( 00000001 00000010 ),则 x 将为 513 ( 00000010 00000001 )。

Here is my code so far:

到目前为止,这是我的代码:

#include <iostream>

using namespace std;

unsigned short int ByteSwap(unsigned short int *x);

int main()
{
  unsigned short int x = 258;
  ByteSwap(&x);

  cout << endl << x << endl;

  system("pause");
  return 0;
}

and

unsigned short int ByteSwap(unsigned short int *x)
{
  long s;
  long byte1[8], byte2[8];

  for (int i = 0; i < 16; i++)
  {
    s = (*x >> i)%2;

    if(i < 8)
    {
      byte1[i] = s;
      cout << byte1[i];
    }
    if(i == 8)
      cout << " ";

    if(i >= 8)
    {
      byte2[i-8] = s;
      cout << byte2[i];
    }
  }

  //Here I need to swap the two bytes
  return *x;
}   

My code has two problems I am hoping you can help me solve.

我的代码有两个问题希望你能帮我解决。

  1. For some reason both of my bytes are 01000000
  2. I really am not sure how I would swap the bytes. My teachers notes on bit manipulation are very broken and hard to follow and do not make much sense me.
  1. 出于某种原因,我的两个字节都是 01000000
  2. 我真的不确定如何交换字节。我的老师关于位操作的笔记非常破碎且难以理解,对我没有多大意义。

Thank you very much in advance. I truly appreciate you helping me.

非常感谢您提前。我真的很感谢你帮助我。

回答by nos

I think you're overcomplicating it, if we assume a short consists of 2 bytes (16 bits), all you need to do is

我认为你把它复杂化了,如果我们假设一个 short 由 2 个字节(16 位)组成,你需要做的就是

  • extract the high byte hibyte = (x & 0xff00) >> 8;
  • extract the low byte lobyte = (x & 0xff);
  • combine them in the reverse order x = lobyte << 8 | hibyte;
  • 提取高字节 hibyte = (x & 0xff00) >> 8;
  • 提取低字节 lobyte = (x & 0xff);
  • 以相反的顺序组合它们 x = lobyte << 8 | hibyte;

回答by Evan Teran

It looks like you are trying to swap them a single bit at a time. That's a bit... crazy. What you need to do is isolate the 2 bytes and then just do some shifting. Let's break it down:

看起来您正试图一次交换一点。这有点……疯狂。您需要做的是隔离 2 个字节,然后进行一些移位。让我们分解一下:

uint16_t x = 258;

uint16_t hi = (x & 0xff00); // isolate the upper byte with the AND operator

uint16_t lo = (x & 0xff); // isolate the lower byte with the AND operator

Now you just need to recombine them in the opposite order:

现在你只需要以相反的顺序重新组合它们:

uint16_t y = (lo << 8); // shift the lower byte to the high position and assign it to y
y |= (hi >> 8);         // OR in the upper half, into the low position

Of course this can be done in less steps. For example:

当然,这可以用更少的步骤完成。例如:

uint16_t y = (lo << 8) | (hi >> 8);

Or to swap without using any temporary variables:

或者不使用任何临时变量进行交换:

uint16_t y = ((x & 0xff) << 8) | ((x & 0xff00) >> 8);       

回答by The Archetypal Paul

You're making hard work of that.

你正在努力工作。

You only neeed exchange the bytes. So work out how to extract the two byte values, then how to re-assemble them the other way around

您只需要交换字节。因此,研究如何提取两个字节值,然后如何以相反的方式重新组装它们

(homework so no full answer given)

(作业所以没有给出完整的答案)

EDIT: Not sure why I bothered :) Usefulness of an answer to a homework question is measured by how much the OP (and maybe other readers) learn, which isn't maximized by giving the answer to the homewortk question directly...

编辑:不知道我为什么要烦恼:) 作业问题答案的有用性是通过 OP(可能还有其他读者)学到的东西来衡量的,这并不能通过直接回答作业问题来最大化......

回答by Brian

Ugly implementation of Jerry's suggestion to treat the short as an array of two bytes:

Jerry 建议的丑陋实现将 short 视为两个字节的数组:

#include <iostream>
typedef union mini
{
    unsigned char b[2];
    short s;
} micro;
int main()
{
    micro x;
    x.s = 258;
    unsigned char tmp = x.b[0];
    x.b[0] = x.b[1];
    x.b[1] = tmp;
    std::cout << x.s << std::endl;
}

回答by Thomas Matthews

Here is an unrolled example to demonstrate byte by byte:

这是一个逐字节演示的展开示例:

unsigned int swap_bytes(unsigned int original_value)
{
  unsigned int new_value = 0; // Start with a known value.
  unsigned int byte;          // Temporary variable.

  // Copy the lowest order byte from the original to
  // the new value:
  byte = original_value & 0xFF;  // Keep only the lowest byte from original value.
  new_value = new_value * 0x100; // Shift one byte left to make room for a new byte.
  new_value |= byte;             // Put the byte, from original, into new value.

  // For the next byte, shift the original value by one byte
  // and repeat the process:
  original_value = original_value >> 8; // 8 bits per byte.
  byte = original_value & 0xFF;  // Keep only the lowest byte from original value.
  new_value = new_value * 0x100; // Shift one byte left to make room for a new byte.
  new_value |= byte;             // Put the byte, from original, into new value.

  //...
  return new_value;
}

回答by Jerry Coffin

While you cando this with bit manipulation, you can also do without, if you prefer. Either way, you shouldn't need any loops though. To do it without bit manipulation, you'd view the shortas an array of two chars, and swap the two chars, in roughly the same way as you would swap two items while (for example) sorting an array.

虽然您可以通过位操作做到这一点,但如果您愿意,也可以不用。无论哪种方式,您都不需要任何循环。要在不进行位操作的情况下执行此操作,您可以将short视为一个包含两个chars的数组,然后交换两个chars,其方式与在(例如)对数组进行排序时交换两个项目大致相同。

To do it with bit manipulation, the swapped version is basically the lower byte shifted left 8 bits ord with the upper half shifted left 8 bits. You'll probably want to treat it as an unsignedtype though, to ensure the upper half doesn't get filled with one bits when you do the right shift.

为了通过位操作来实现,交换版本基本上是低字节左移 8 位ord,上半部分左移 8 位。不过,您可能希望将其视为一种unsigned类型,以确保在进行右移时不会填充上半部分。

回答by Kenny Cason

This should also work for you.

这也应该对你有用。

#include <iostream>

int main() {
    unsigned int i = 0xCCFF;
    std::cout << std::hex << i << std::endl;

    i  = ( ((i<<8) & 0xFFFF) | ((i >>8) & 0xFFFF)); // swaps the bytes

    std::cout << std::hex << i << std::endl;
}

回答by Poorna

#include <stdio.h>

int main()
{
   unsigned short a = 258;
   a = (a>>8)|((a&0xff)<<8);
   printf("%d",a);
}

回答by Skizz

This is a problem:

这是个问题:

byte2[i-8] = s;
cout << byte2[i];//<--should be i-8 as well

This is causing a buffer overrun.

这会导致缓冲区溢出。

However, that's not a great way to do it. Look into the bit shift operators << and >>.

但是,这不是一个很好的方法。查看位移运算符 << 和 >>。

回答by don bright

A bit old fashioned, but still a good bit of fun.

有点老式,但仍然很有趣。

XOR swap: ( see How does XOR variable swapping work?)

XOR 交换:(请参阅XOR 变量交换如何工作?

    #include <iostream>
    #include <stdint.h>
    int main()
    {
        uint16_t x = 0x1234;
        uint8_t *a = reinterpret_cast<uint8_t*>(&x);
        std::cout << std::hex << x << std::endl;
        *(a+0) ^= *(a+1) ^= *(a+0) ^= *(a+1);
        std::cout << std::hex << x << std::endl;
    }