2010-10-12 37 views
5

Estoy trabajando en una tarea para mi clase de C++. La pregunta en la que estoy trabajando dice lo siguiente:Intercambio de bytes enteros en C++

Escriba una función que toma un int corto sin signo (2 bytes) y cambia los bytes. Por ejemplo, si x = 258 (00000001 00000010) después del intercambio, x será 513 (00000010 00000001).

Aquí está mi código hasta ahora:

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

y

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

Mi código tiene dos problemas que estoy esperando que usted puede ayudar a resolver.

  1. Por alguna razón mis dos bytes son 01 millones
  2. Realmente no estoy seguro de cómo iba a cambiar los bytes. Las notas de mis maestros sobre la manipulación de bits son muy rotas y difíciles de seguir y no tienen mucho sentido para mí.

Muchas gracias de antemano. Realmente aprecio que me hayas ayudado.

+0

Las quejas sobre el código: 1) Me refiero pasar el corto directamente en lugar de como un puntero. Como está escrito, su función intenta editar la variable pasada, lo que es bastante feo. 2) Si insistes en modificar la variable a medida que se pasa, no me molestaría en devolverla (esto hace que sea sorprendente que tu función la edite) y usaría pasar por referencia en lugar de pasar un puntero. 3) Preferiría usar operadores de bits y simplemente usar una matriz de dos bytes ('char' o' unsigned char'), en lugar de almacenar cada bit en un largo separado. – Brian

+0

Consulte también una pregunta algo relacionada: http://stackoverflow.com/questions/3991478/building-a-32bit-float-out-of-its-4-composite-bytes-c – Brian

Respuesta

19

Pienso que usted es complicar que, si suponemos un corto consta de 2 bytes (16 bits), todo lo que necesita hacer es a

  • extraer el byte alto hibyte = (x & 0xff00) >> 8;
  • extraer la baja byte lobyte = (x & 0xff);
  • ellos se combinan en el orden inverso x = lobyte << 8 | hibyte;
+0

No estoy familiarizado con esa sintaxis. ¿Me puede dar una referencia por favor? –

+2

@Rob S.: '&': en bits y operación. '>>' y '<<': Operaciones de cambio de bit. '|': Bitwise u operación. Esa es una explicación suficiente para hacer que Google sea realmente fácil. O simplemente lea http://en.wikipedia.org/wiki/Bitwise_operation – Brian

1

Mientras que puede hacer esto con la manipulación de bits, también puede prescindir, si lo prefiere. De cualquier manera, no deberías necesitar ningún bucle. Para hacerlo sin la manipulación de bits, verá el short como una matriz de dos char s, e intercambiará los dos char s, aproximadamente de la misma manera que si intercambiara dos elementos mientras (por ejemplo) ordenaba una matriz.

Para hacerlo con la manipulación de bits, la versión intercambiada es básicamente el byte inferior desplazado a la izquierda 8 bits or d con la mitad superior desplazada a la izquierda 8 bits. Sin embargo, es probable que desee tratarlo como un tipo unsigned, para asegurarse de que la mitad superior no se llene con un bit cuando realiza el desplazamiento correcto.

+0

Entonces, sin la manipulación de bits, ¿está hablando de ¿Encasillar el corto en un char y romperlo por la mitad? No tengo mucha experiencia con esto, pero creo que sería interesante intentarlo. –

+0

@Rob S .: Normalmente tomaría su dirección y lo convertiría en puntero a char, o podría usar una unión de los dos tipos ('short' y' char [2] '). Sin una razón para hacer lo contrario, probablemente usaría el puntero. –

5

Estás haciendo el trabajo duro de ello.

Sólo necesita cambiar los bytes. Así funciona la manera de extraer los dos valores de bytes, a continuación, cómo ellos volver a montar al revés

(tarea por lo que no da respuesta completa)

EDIT: No sé por qué me molesta :) utilidad de una La respuesta a una pregunta de tarea se mide por cuánto aprenden los OP (y tal vez otros lectores), que no se maximiza respondiendo directamente a la pregunta de homewortk ...

+0

¿Puede proporcionarme alguna referencia o material de lectura sobre esto? Creo que la mayor parte de mi problema es que carezco de muchos conocimientos básicos sobre este tema. –

+0

@Rob S.: Una forma de hacerlo es con una 'unión'. Ver mi respuesta para un ejemplo. Otra forma de hacerlo es mediante el feo lanzamiento de punteros. P.ej.\t 'short s = 258; unsigned char tmp = (* (unsigned char *) (&s))'; Probablemente haya una mejor manera. – Brian

+0

@RobS si realmente está tomando una clase de C++ debe haber materiales de clase para eso. Si la clase no los proporciona, encuentre una clase diferente! Usted está haciendo algunas preguntas muy básicas y no debería necesitar punteros a las respuestas (por ejemplo, el significado de << etc) –

5

Parece que estás intentando cambiarlos un solo bit a la vez. Eso es un poco ... loco.Lo que necesita hacer es aislar los 2 bytes y luego hacer algunos cambios. Vamos a desglosarlo:

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 

Ahora sólo tiene que recombinar en el orden contrario:

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 

Por supuesto, esto se puede hacer en menos pasos. Por ejemplo:

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

O para intercambiar sin necesidad de utilizar ninguna de las variables temporales:

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

+1 agradable, parece que todos pueden escribir respuestas mucho más rápido y mejor que yo: D –

+0

Esto funciona y realmente aprecio su respuesta. ¿Puede proporcionar cualquier referencia o material de lectura sobre cómo funciona? Particularmente en lo que el '&' y '| 'personajes hacen. Muchas gracias de nuevo :) –

+0

Esos son los operadores de bit lógico AND y OR en C. http://en.wikipedia.org/wiki/Bitwise_operation –

0

Este es un problema:

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

Esto está provocando una saturación del búfer.

Sin embargo, esa no es una buena manera de hacerlo. Mire en los operadores de cambio de bit < < y >>.

1

Esto también debería funcionar para usted.

#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
#include <stdio.h> 


int main() 
{ 
    unsigned short a = 258; 

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

    printf("%d",a); 


} 
3

aplicación feo de la sugerencia de Jerry para tratar el corto como una matriz de dos bytes:

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

Muchas gracias por esto. Esto me ayuda mucho :) –

+0

¿Alguna razón por la que evitaste 'std :: swap()'? – genpfault

+0

@genpfault: No. – Brian

3

Aquí es un ejemplo desenrollado para demostrar byte a 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; 
} 
+1

buen comentario –

0

Un poco pasado de moda, pero aún así es un poco divertido.

XOR de intercambio: (ver How does XOR variable swapping work?)

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