Целочисленная замена байтов в C ++ - PullRequest
7 голосов
/ 12 октября 2010

Я работаю над домашним заданием для моего класса C ++. Вопрос, над которым я работаю, гласит:

Напишите функцию, которая принимает unsigned short int (2 байта) и заменяет байты. Например, если x = 258 (00000001 00000010) после обмена, x будет 513 (00000010 00000001).

Вот мой код:

#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;
}

и

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;
}   

В моем коде есть две проблемы, надеюсь, вы поможете мне решить.

  1. Почему-то оба моих байта - 01000000
  2. Я действительно не уверен, как бы я поменял байты. Мои заметки учителей о битовых манипуляциях очень разбиты и им трудно следовать, и они не имеют особого смысла для меня.

Большое спасибо заранее. Я действительно ценю, что вы помогаете мне.

Ответы [ 11 ]

20 голосов
/ 12 октября 2010

Я думаю, что вы слишком усложняете это, если мы предположим, что короткое замыкание состоит из 2 байтов (16 бит), все, что вам нужно сделать, это

  • извлечь старший байт hibyte = (x & 0xff00) >> 8;
  • извлечь младший байт lobyte = (x & 0xff);
  • объединить их в обратном порядке x = lobyte << 8 | hibyte;
7 голосов
/ 12 октября 2010

Похоже, вы пытаетесь поменять их местами по одному.Это немного ... безумно.Что вам нужно сделать, это изолировать 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

Теперь вам нужно просто объединить их в обратном порядке:

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

Конечно, это можно сделать за меньшее количество шагов.Например:

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

Или для замены без использования временных переменных:

uint16_t y = ((x & 0xff) << 8) | ((x & 0xff00) >> 8);       
4 голосов
/ 12 октября 2010

Ты усердно работаешь над этим.

Вам нужно только обменять байты. Так что подумайте, как извлечь два байтовых значения, а затем собрать их наоборот

(домашнее задание, поэтому полный ответ не дан)

РЕДАКТИРОВАТЬ: Не знаю, почему я беспокоился :) Полезность ответа на домашнее задание измеряется тем, как много изучают ОП (и, возможно, другие читатели), что не максимизируется путем непосредственного ответа на вопрос о домашнем задании. ..

3 голосов
/ 12 октября 2010

Вот развернутый пример для демонстрации побайтно:

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;
}
3 голосов
/ 12 октября 2010

Уродливая реализация предложения Джерри рассматривать короткое как массив из двух байтов:

#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;
}
1 голос
/ 12 октября 2010
#include <stdio.h>


int main()
{
   unsigned short a = 258;

   a = (a>>8)|((a&0xff)<<8);

   printf("%d",a);


}
1 голос
/ 12 октября 2010

Это также должно работать для вас.

#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;
}
1 голос
/ 12 октября 2010

Хотя вы можете делать это с помощью битовых манипуляций, вы также можете обойтись без них, если хотите. В любом случае, вам не нужны петли. Чтобы сделать это без битовых манипуляций, вы бы рассматривали short как массив из двух char s и меняли местами два char s примерно так же, как вы бы поменяли местами два элемента во время (например) сортировка массива.

Чтобы сделать это с помощью битовых манипуляций, замененная версия - это, как правило, сдвинутый младший байт влево на 8 бит or d со сдвинутой верхней половиной влево на 8 бит. Возможно, вы захотите рассматривать его как тип unsigned, чтобы верхняя половина не заполнялась ни одним битом, когда вы делаете правильный сдвиг.

0 голосов
/ 18 ноября 2018

При использовании библиотечных функций может пригодиться следующий код (в контексте не домашней работы):

unsigned long swap_bytes_with_value_size(unsigned long value, unsigned int value_size) {
    switch (value_size) {
        case sizeof(char):
            return value;

        case sizeof(short):
            return _byteswap_ushort(static_cast<unsigned short>(value));

        case sizeof(int):
            return _byteswap_ulong(value);

        case sizeof(long long):
            return static_cast<unsigned long>(_byteswap_uint64(value));

        default:
            printf("Invalid value size");
            return 0;
    }
}

Функции перестановки байтов определены в stdlib.h, по крайней мере, при использовании MinGW набор инструментов.

0 голосов
/ 02 февраля 2013

Немного старомодно, но все равно немного веселья.

XOR swap: (см. Как работает замена 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;
    }
...