c++ - tiempo - precio bitcoin historico 2018
cambio de bit-cambio de un valor cambiado (3)
Elimine los bits adicionales enmascarando con 0xFF
:
result = (((value << 3) & 0xFF) >> 2);
También puede recortar los tres bits superiores después de la secuencia de turnos:
result = 0x1F & ((value << 3) >> 2);
De acuerdo con la especificación del lenguaje, las promociones enteras por defecto se aplican a los operandos de cambio antes del cambio, y el resultado de la operación es el tipo promovido del primer operando.
5.8.1 Los operandos serán de tipo integral o enumerado y se realizarán promociones integrales. El tipo de resultado es el del operando izquierdo promovido.
Si un tipo integral puede caber en un int
, entonces int
es el resultado de la promoción. Cuando se desplaza hacia la izquierda, los bits más significativos se "derraman" en la parte superior de la int
. Su primer fragmento los corta asignándolos de nuevo al byte
; puede lograr el mismo resultado enmascarando el resultado con 0xFF
.
He intentado hacer una función más larga, pero ha actuado de forma muy extraña. Intenté aislar el problema y pude encontrar la parte defectuosa.
Este programa hizo para un Arduino, pero este fenómeno probablemente aparezca en otro entorno. He intentado hacer muchas búsquedas pero no puedo encontrar la solución.
Entonces, mi parte con errores:
¿Por qué estos dos códigos no dan el mismo resultado?
¿Cómo puedo construir una función de una línea sin variable adicional?
pero la misma operación como "Código 1"?
Resultados:
- Código 1: 0b00101100
- Código 2: 0b01101100
Códigos fuente:
Código 1: (operación correcta pero no una línea)
#include <binary.h>
const byte value=B00110110;
byte buffer,result;
void setup(){
Serial.begin(115200);
buffer = (value << 3);
result = (buffer >> 2);
Serial.println(result,BIN);
}
void loop(){
}
Da: 0b00101100
Código 2: (operación incorrecta pero una línea)
#include <binary.h>
const byte value=B00110110;
byte result;
void setup(){
Serial.begin(115200);
result = ((value << 3) >> 2);
Serial.println(result,BIN);
}
void loop(){
}
Da: 0b01101100
Si byte
es un uint8_t
(¡gracias, Sr. Fernandes!), El resultado de (value << 3)
es más ancho que un byte
. Más precisamente, el value
se promueve a un tipo más amplio antes de que ocurra el cambio, y el resultado es ese tipo más amplio. Para obtener el comportamiento del Código 1, puede cambiar el Código 2 para hacer esto:
result = (static_cast<byte>(value << 3) >> 2);
Esto imita la asignación intermedia para buffer
en el código 1 con un molde.
Supongo que su byte
es un tipo integral sin signo más pequeño que int
.
La mayoría de las operaciones aritméticas en C ++ se realizan en el dominio de tipo int
, después de que todos los operandos "más pequeños" se convierten implícitamente ( promocionados ) a tipo int
.
Por esta razón, su primer grupo de turnos equivale a
buffer = (byte) ((int) value << 3);
result = (byte) ((int) buffer >> 2);
mientras que su segundo grupo si turnos es equivalente a
result = (byte) (((int) value << 3) >> 2);
En la primera variante, los bits que se desplazan fuera del rango del byte
de tipo por el cambio << 3
se pierden durante la conversión intermedia y la asignación al buffer
. En la segunda variante, todos los cálculos se realizan dentro del rango de int
, por lo que no se pierde nada.
Si desea que su segunda variante produzca los mismos resultados que la primera, debe "truncar" explícitamente el resultado del cambio intermedio.
result = ((byte) (value << 3) >> 2);