Con frecuencia deseo poder hacer algo como esto en c:
val1 &= 0b00001111; //clear high nibble
val2 |= 0b01000000; //set bit 7
val3 &= ~0b00010000; //clear bit 5
Tener esta sintaxis parece una adición increíblemente útil a C sin inconvenientes que se me ocurran, y parece algo natural para un lenguaje de bajo nivel donde el juego de bits es bastante común.
Editar: estoy viendo algunas otras excelentes alternativas, pero todas se desmoronan cuando hay una máscara más compleja. Por ejemplo, si reg es un registro que controla los pines de E/S en un microcontrolador, y quiero configurar los pines 2, 3 y 7 altos al mismo tiempo que podría escribir reg = 0x46; pero tuve que pasar 10 segundos pensando en ello (y probablemente tendré que pasar 10 segundos nuevamente cada vez que lea ese código después de no mirarlo por un día o dos) o podría escribir reg = (1 << 1) | (1 << 2) | (1 << 6); pero personalmente creo que es mucho menos claro que simplemente escribir `reg = 0b01000110;’ Sin embargo, puedo estar de acuerdo en que no se escala mucho más allá de las arquitecturas de 8 bits o quizás de 16 bits. No es que alguna vez haya necesitado hacer una máscara de 32 bits.
tiene maleficio, que en mi opinión es incluso mejor, si dedicas 10 minutos a sentir la relación
– vroomfondel
15 de agosto de 2013 a las 1:00
C tiene literales “binarios”, pero solo 2 de ellos: 0, 1. 😉
– chux – Reincorporar a Monica
15 de agosto de 2013 a las 4:25
Por lo que vale, C ++ 14 tendrá estos.
– Nemo
15 de agosto de 2013 a las 5:19
#define B00000000 0#define B00000001 1#define B00000010 2#define B00000011 3 … #define B10100100 0xA4 … posiblemente con un yeso para unsigned char.
Eso es increíble, pero no estoy usando GCC 🙁 ¿sabes qué no está en el estándar?
– Dibujó
15 de agosto de 2013 a las 1:08
@Drew Ver la actualización. En otras palabras, creo que el comité cree que su uso puede cubrirse con constantes hexadecimales.
– YuHao
15 de agosto de 2013 a las 1:24
A veces pienso que las personas que escriben estándares en realidad no codifican nada en el lenguaje que están estandarizando. Eso, o todos son parte del mismo espacio tecnológico de nicho y no pueden comprender que alguien use el lenguaje para otra cosa que no sea para lo que lo usan.
– Kurt E. Clothier
22 de febrero a las 2:33
jacob pollock
Esto es lo que empujó hexadecimal ser… hexadecimal. Los “… El uso principal de la notación hexadecimal es una representación humana de valores codificados en binario en computación y electrónica digital…“. Sería de la siguiente manera:
val1 |= 0xF;
val2 &= 0x40;
val3 |= ~0x10;
hexadecimal:
Un dígito hexadecimal puede representar un nibble (4 bits o medio octal).
Dos dígitos hexadecimales pueden representar un byte (8 bits).
Hex es mucho más compacto cuando se escala a máscaras más grandes.
Con algo de práctica, la conversión entre hexadecimal y binario será mucho más natural. Trate de escribir sus conversiones a mano y no use un convertidor de notación hexadecimal/bin en línea; luego, en un par de días, se volverá natural (y más rápido como resultado).
Aparte: Aunque los literales binarios no son un estándar de C, si compila con GCC es posible usar literales binarios, deben tener el prefijo ‘0b’ o ‘0B’. Ver la documentación oficial aquí para mayor información. Ejemplo:
int b1 = 0b1001; // => 9
int b2 = 0B1001; // => 9
Sí, eso es lo que siempre termino haciendo, pero siempre tengo que hacer un montón de cálculos en mi para recordar qué binario es qué en hax. Especialmente si quiero, por ejemplo. borrar los 6 bits más bajos. Y estoy de acuerdo en que los literales binarios se alargarían para las plataformas de 32 bits, pero en ese caso simplemente no puedes usarlos.
– Dibujó
15 de agosto de 2013 a las 1:06
Pensar en maleficio se convierte en una segunda naturaleza después de un poco de práctica. Hex también tiene la ventaja de que es más fácil de leer que binario.
– markgz
15 de agosto de 2013 a las 1:08
@Drew, entiendo tu punto de vista, ya que puede ser visualmente mucho más fácil pensar en máscaras más pequeñas. Una vez que hayas practicado lo suficiente, te resultará bastante natural (como todo sucede en la vida). Recomiendo hacer todos los cálculos a mano y verificar dos veces en una calculadora al crear máscaras para que pueda mejorar y convertir entre las dos notaciones.
–Jacob Pollack
15 de agosto de 2013 a las 1:09
¿Cuánto cálculo mental se necesita realmente para imaginar el valor binario representado por un número hexadecimal? De todas las operaciones/cálculos que un buen programador necesita hacer en su cabeza, creo que esta es una de las más sencillas.
– acechador
15 de agosto de 2013 a las 1:40
cambie “4 bytes” a “4 bits” en el punto 1. Un nibble es 4 bits, no bytes.
– Hans Dampf
06/10/2015 a las 11:40
Nemo
Todos sus ejemplos se pueden escribir aún más claramente:
val1 &= (1 << 4) - 1; //clear high nibble
val2 |= (1 << 6); //set bit 6
val3 &=~(1 << 3); //clear bit 3
(Me he tomado la libertad de arreglar los comentarios para que cuenten desde cero, como pretendía Nature).
Su compilador plegará estas constantes, por lo que no hay penalización de rendimiento al escribirlas de esta manera. Y estos son más fáciles de leer que los 0b... versiones.
@Jerry Bueno, eso me enseñará a no dejar de pensar después del primer error. Gracias
– Nemo
15 de agosto de 2013 a las 1:59
Si tenemos en cuenta la endianidad, es (1 << 4) - 1 realmente lo mismo que 0xF ? … tal vez no.
– Abraham Sánchez
1 de septiembre de 2015 a las 1:54
@AbrahamSanchez: Sí, es exactamente igual en todas las plataformas. Las operaciones aritméticas como el desplazamiento a la izquierda se definen independientemente del endian. (De hecho, el endianness ni siquiera es detectable a menos que emita un puntero o use una unión).
– Nemo
1 de septiembre de 2015 a las 3:47
@Nemo o una matriz, una estructura o cualquier otra variable. Mientras uses algún truco como el memcpy, todo es posible.
– yyny
2 de marzo de 2016 a las 23:43
@YoYoYonnY: Todo eso requiere que “lances un puntero o uses una unión”, como dije.
– Nemo
02/03/2016 a las 23:51
Creo que la legibilidad es una preocupación principal. Aunque de bajo nivel, son los seres humanos quienes leen y mantienen su código, no la máquina.
¿Es fácil para ti darte cuenta de que escribiste por error? 0b1000000000000000000000000000000(0x40000000)donde realmente quieres decir 0b10000000000000000000000000000000(0x80000000) ?
“Por ejemplo, si reg es un registro que controla los pines de E/S en un microcontrolador”
No puedo evitar pensar que este es un mal ejemplo. Los bits en los registros de control tienen funciones específicas (al igual que cualquier dispositivo conectado a bits de E/S individuales).
Sería mucho más sensato proporcionar constantes simbólicas para patrones de bits en un archivo de encabezado, en lugar de calcular el binario dentro del código. Convertir binario a hexadecimal u octal es trivial, recordar lo que sucede cuando escribe 01000110 en un registro IO no lo es, especialmente si no tiene a mano la hoja de datos o el diagrama del circuito.
¡Entonces no solo ahorrará esos 10 segundos tratando de descifrar el código binario, sino tal vez un poco más de tiempo tratando de descifrar lo que hace!
philip1611
Recomiendo macros C en C para evitar advertencias del compilador u otros problemas. En lugar de 0x, uso Ox (como en “Ohio”).
/* binmacro.h */
#define BX_0000 0
#define BX_0001 1
#define BX_0010 2
#define BX_0011 3
#define BX_0100 4
#define BX_0101 5
#define BX_0110 6
#define BX_0111 7
#define BX_1000 8
#define BX_1001 9
#define BX_1010 A
#define BX_1011 B
#define BX_1100 C
#define BX_1101 D
#define BX_1110 E
#define BX_1111 F
#define BIN_A(x) BX_ ## x
#define BIN_B(x,y) 0x ## x ## y
#define BIN_C(x,y) BIN_B(x,y)
#define BIN_B4(x,y,z,t) 0x ## x ## y ## z ## t
#define BIN_C4(x,y,z,t) BIN_B4(x,y,z,t)
#define BIN(x,y) BIN_C(BIN_A(x),BIN_A(y))
#define BIN4(x,y,z,t) BIN_C4(BIN_A(x),BIN_A(y),BIN_A(z),BIN_A
/*---- test ... ---*/
BIN(1101,0100)
BIN4(1101,0010,1100,0101)
¿Qué preprocesos para…
$ cpp binmacro.h
0xD4
0xD2C5
¿Ha sido útil esta solución?
Tu feedback nos ayuda a saber si la solución es correcta y está funcionando. De esta manera podemos revisar y corregir el contenido.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
tiene maleficio, que en mi opinión es incluso mejor, si dedicas 10 minutos a sentir la relación
– vroomfondel
15 de agosto de 2013 a las 1:00
C tiene literales “binarios”, pero solo 2 de ellos: 0, 1. 😉
– chux – Reincorporar a Monica
15 de agosto de 2013 a las 4:25
Por lo que vale, C ++ 14 tendrá estos.
– Nemo
15 de agosto de 2013 a las 5:19
#define B00000000 0
#define B00000001 1
#define B00000010 2
#define B00000011 3
…#define B10100100 0xA4
… posiblemente con un yeso paraunsigned char
.– pmg
25 de julio de 2017 a las 18:52
@AnT: más precisamente,
0
es un constante octal– chqrlie
25 de agosto de 2018 a las 8:24