Tengo un número hexadecimal 0x37 y su representación binaria es 0011 0111. ¿Cómo accedo a los primeros 2 bits de la representación binaria que es "11"? ¿Cómo uso el cambio de bits o el enmascaramiento para lograr esto? Puedo acceder poco a poco, pero no dos bits de una vez?Bits de acceso en un carácter en C
Respuesta
Si su número es &
con 0x03, obtendrá los dos últimos bits.
char c = 0x37;
char mask = 0x03;
char lastTwo = c & mask;
Su mejor opción es utilizar el enmascaramiento de bits, como se había mencionado. Algo como esto debe hacer el truco:
x = 0x37;
y = x&0x30; //Mask out the first two bits of the higher nibble
y = y>>4;
Este es un ejemplo para acceder a ella poco a poco:
#include <stdio.h>
int main()
{
char byte = 0x37;
int i;
for(i = 7; 0 <= i; i --)
printf("%d\n", (byte >> i) & 0x01);
return 0;
}
También puede utilizar campos de bits para hacer esto. La parte mala de los campos de bits es que exactamente cómo funcionan depende de algún modo del compilador, pero si no necesitas transferir el código a muchas arquitecturas, quizás esté bien.
Aquí hay un ejemplo, escrito en una computadora Ubuntu Linux y probado con GCC.
#include <assert.h>
#include <stdio.h>
#pragma pack(1)
typedef struct
{
unsigned int low2: 2; // 2 bits of the byte
unsigned int high6: 6; // 6 more bits of the byte
} MYBYTE;
typedef union
{
MYBYTE mybyte;
unsigned char b;
} MYUNION;
main()
{
MYUNION m;
assert(sizeof(m) == 1);
m.b = 0x03;
assert(m.mybyte.low2 == 0x03);
assert(m.mybyte.high6 == 0x00);
printf("low2 of 0x03 is: %u\n", m.mybyte.low2);
printf("high6 of 0x03 is: %u\n", m.mybyte.high6);
m.b = 0xff;
printf("low2 of 0x03 is: %u\n", m.mybyte.low2);
printf("high6 of 0x03 is: %u\n", m.mybyte.high6);
assert(m.mybyte.low2 == 0x03);
assert(m.mybyte.high6 == 0x3f);
m.mybyte.high6 = 0x1c;
m.mybyte.low2 = 0x01;
assert(m.b == 0x71);
printf("m.b is: 0x%02x\n", m.b);
return 0;
}
la Unión está allí, así que se puede acceder a él como un byte completo o acceder a él por los campos de bits. #pragma pack(1)
está ahí para asegurarse de que los campos de bits se empaquetan en un byte, sin bits de "relleno" adicionales. (Como dije antes, confía en los detalles de implementación cuando usa campos de bits.)
Pero vea qué sencillo y limpio es acceder a los bits que desea. Puede escribir en un byte completo y leer los bits que desee, o escribir los bits que desee y leer todo el byte.
Si vas a utilizar un código como este, siempre es una buena idea tener algunas afirmaciones que aseguren que está funcionando.
Si no va a utilizar campos de bits, le sugiero que defina una función que realice su cambio y enmascaramiento para usted, para asegurarse de que no se equivoca. Tal vez algo como esto:
#include <limits.h>
static unsigned int _bit_masks[] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007,
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
};
#define MIN(a, b) \
((a) < (b) ? (a) : (b))
unsigned int
bits(unsigned int x, unsigned int i_bit, unsigned int c_bits)
{
assert(UINT_MAX >= 4294967295U); // unsigned int must be at least 32-bit
assert(i_bit <= 31);
if (i_bit > 31)
return 0;
c_bits = MIN(c_bits, 32 - i_bit);
// shift-and-mask to grab the requested bits, and return those bits
return (x >> i_bit) & _bit_masks[c_bits];
}
Se pasa de un valor y, a continuación, que se mordió posición que desee bits de, y la cantidad de bits que desea. Así que para agarrar 6 bits a partir de la posición de bit 2, con un valor de prueba de 0x71 que se podría llamar:
x = bits(0x71, 2, 6); // x is set to 0x1c
Si no te gusta la tabla de consulta, y desea que el código más pequeño para hacer esto, usted puede utilizar:
unsigned int
bits(unsigned int x, unsigned int i_bit, unsigned int c_bits)
{
const unsigned int mask_bits = 0xffffffff;
assert(UINT_MAX >= 4294967295U); // unsigned int must be at least 32-bit
assert(i_bit <= 31);
if (i_bit > 31)
return 0;
c_bits = MIN(c_bits, 32 - i_bit);
// shift-and-mask to grab the requested bits, and return those bits
return (x >> i_bit) & (mask_bits >> (32 - c_bits));
}
Es necesario asegurarse de que los bits de máscara se declaran unsigned
porque si llevan la firma, la operación de desplazamiento a la derecha firmará a extender.
Si declara esta última versión de la función como en línea, la coloca en archivos de encabezado y la llama con valores constantes para i_bit
y c_bits
, se compilará hasta el código mínimo para resolver el problema. (Por ejemplo, si i_bit
es 0, el compilador sabe que >> 0
no hace nada y no generará ese código. Y si el compilador conoce c_bits
como una constante, puede hacer todo el trabajo de cambiar mask_bits
en tiempo de compilación.) Pero necesitará asegurarse de que está utilizando una versión de assert()
que se compila en cero en su compilación de lanzamiento, o bien use su propia macro ASSERT()
y haga que su compilación de macro quede en nada.
Esta es la función más fácil de usar, no quiero que otros luchan por un largo tiempo antes de conseguir algo similar a esto -
char get_bits(char a, char no_of_bits)
{
return a & ((no_of_bits << 1) - 1);
}
char a = 0x37;
char b = get_bits(a, 2);
espero que ayude a alguien en el futuro
- 1. Lectura de un archivo carácter por carácter en C
- 2. Campos de bits en C#
- 3. ¿Cambios de bits en un puntero C?
- 4. C# añadiendo un carácter en una cadena
- 5. Acceso a la ruta de destino desde un archivo de acceso directo en un sistema de 64 bits utilizando la aplicación de 32 bits
- 6. Lectura en 16 bits de un registro de 32 bits
- 7. Cómo convertir un carácter ascii en un int en C
- 8. vectores de bits en C++
- 9. Rotación de bits en C
- 10. Bits de configuración en C
- 11. Arreglo de bits en C++
- 12. Reemplazar el carácter "en C#
- 13. Cómo sustituir bits en un campo de bits sin afectar a otros bits utilizando c
- 14. Tamaño del carácter ('a') en C/C++
- 15. Acceso de registro con C# y "BUILD x86" en una máquina de 64 bits
- 16. Convierta un dígito de carácter al entero correspondiente en C
- 17. ¿Cómo encuentro el tipo de carácter bidireccional de un carácter Unicode en C#?
- 18. Dividir en un carácter único
- 19. Cómo leer desde un archivo de texto, carácter por carácter en C++
- 20. enum de 8 bits, en C
- 21. escribiendo 'bits' en secuencias de archivos C++
- 22. C# PInvitando user32.dll en un sistema de 64 bits
- 23. sesión extender un número de nueve bits en C
- 24. C#: Dibujar un mapa de bits en otro, con transparencia
- 25. ¿Qué es un mapa de bits en C?
- 26. Afilar en un mapa de bits usando C#
- 27. Cómo invertir en bits AND (&) en C?
- 28. RC4 Encriptación de 128 bits en C#
- 29. ¿Cómo compilar un programa C++ como de 64 bits en una máquina de 64 bits?
- 30. acceso variable concurrente en c
Aquí, suponía que quería aislar el 11 del "0011". Si solo necesita los dos bits de orden más bajo, x & 0x03 funcionaría, como lo ha demostrado dasblinkenlight. – zje