Pregunta

Me estaba ayudando a alguien con sus tareas y se topó con este extraño asunto. El problema es escribir una función que invierte el orden de bytes de un entero con signo (así es como se ha especificado la función de todos modos), y esta es la solución que se me ocurrió:

int reverse(int x)
{
    int reversed = 0;

    reversed = (x & (0xFF << 24)) >> 24;
    reversed |= (x & (0xFF << 16)) >> 8;
    reversed |= (x & (0xFF << 8)) << 8;
    reversed |= (x & 0xFF) << 24;

    return reversed;
}

Si pasa 0xFF000000 a esta función, la primera tarea resultará en 0xFFFFFFFF. Realmente no entiendo lo que está pasando, pero sé que tiene algo que ver con las conversiones de ida y vuelta entre firmado y sin firmar, o algo por el estilo.

Si bien ul anexados para 0xFF funciona bien, que yo supongo que es porque está obligado a firmar luego se convierte a firmado o algo en esa dirección. El código resultante también cambia; sin el especificador ul que utiliza sar (desplazamiento aritmético a la derecha), pero como sin signo que utiliza SHR como se pretende.

Realmente agradecería que si alguien puede arrojar algo de luz sobre esto para mí. Se supone que tengo que saber estas cosas, y creo que lo hice, pero estoy realmente seguro de lo que está pasando aquí.

Gracias de antemano!

¿Fue útil?

Solución

Desde x es un firmado cantidad, el resultado de (x & (0xFF << 24)) es 0xFF000000 que también se firma y por lo tanto un número desde está ajustado negativo de la parte superior (signo) bits. El operador >> en int (un valor con signo) realiza extensión de signo (Editar: aunque este comportamiento no está definido y la aplicación específica) y se propaga el valor de bit de signo de 1 como el valor se desplaza a la derecha.

Se debe reescribir la función de la siguiente manera para trabajar exclusivamente en valores sin signo:

unsigned reverse(unsigned x)
{
    unsigned int reversed = 0;

    reversed = (x & (0xFF << 24)) >> 24;
    reversed |= (x & (0xFF << 16)) >> 8;
    reversed |= (x & (0xFF << 8)) << 8;
    reversed |= (x & 0xFF) << 24;

    return reversed;
}

Otros consejos

A partir de los resultados se puede deducir que usted está en una máquina de 32 bits.

(x & (0xFF << 24)) >> 24

En este 0xFF expresión es un int, por lo 0xFF << 24 es también un int, como es x.

Al realizar la & bit a bit entre dos int, el resultado es también un int y en este caso el valor es 0xFF000000 que por un medio de máquinas de 32 bits que el bit de signo se establece, por lo que tiene un número negativo.

El resultado de realizar un desplazamiento a la derecha en un objeto de tipo firmado con un valor negativo es definido por la implementación. En su caso, tal como se realiza el inicio de sesión preservar la aritmética desplazamiento a la derecha.

Si desplazamiento a la derecha de un tipo sin signo, a continuación, se podrían obtener los resultados que usted esperaba para una función de inversión de bytes. Se podría lograr esto haciendo alguno de los operandos de la & bit a bit de operando un tipo de forzar la conversión sin signo de los dos operandos al tipo sin signo. (Esto es cierto en cualquier aplicación donde un int firmado no puede contener todo el rango posible de valores positivos de una unsigned int que es casi todas las implementaciones.)

Desplazamiento a la derecha en los tipos firmados se define la aplicación, en particular, el compilador es libre de hacer un desplazamiento aritmético o lógico como le plazca. Esto es algo que no se dé cuenta si el valor concreto que se está tratando es positivo, pero tan pronto como es negativo se podría caer en una trampa.

Pero no lo hace, esto no es portátil.

x está firmado, por lo que el bit más alto se utiliza para la señal. 0xFF000000 medios "negativo 0x7F000000". Cuando lo haga el cambio, el resultado es "signo extendido": El dígito binario que se añadió a la izquierda para sustituir el antiguo MSB que se desplaza a la derecha, es siempre el mismo que el signo del valor. Así

0xFF000000 >> 1 == 0xFF800000
0xFF000000 >> 2 == 0xFFC00000
0xFF000000 >> 3 == 0xFFE00000
0xFF000000 >> 4 == 0xFFF00000

Si el ser desplazado valor está sin firmar, o si el desplazamiento es hacia la izquierda, el nuevo bit sería 0. Es sólo en la derecha turnos de valores con signo de que la extensión con signo entran en juego.

Si quieres que funcione de la misma sobre el Al plataformas con dos números enteros con y sin signo, el cambio

(x & (0xFF << 24)) >> 24

en

(x >> 24) & 0xFF

Si este es el código de Java debe utilizar '>>>', que es un desplazamiento sin signo derecha, si no se firman extender el valor

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top