У меня есть шестнадцатеричное число 0x37, а его двоичное представление 0011 0111. Как мне получить доступ к первым двум битам двоичного представления, которое равно «11»? Как использовать бит-сдвиг или маскирование для достижения этого? Я могу получить доступ к бит за битом, но не два бита за один раз?Доступ к битам в char в C
ответ
Если у вас &
ваш номер с 0x03, вы получите последние два бита.
char c = 0x37;
char mask = 0x03;
char lastTwo = c & mask;
Ваш лучший выбор - использовать битовую маскировку, как вы уже упоминали. Что-то вроде этого следует сделать трюк:
x = 0x37;
y = x&0x30; //Mask out the first two bits of the higher nibble
y = y>>4;
Вот пример, чтобы получить доступ к его по кусочкам:
#include <stdio.h>
int main()
{
char byte = 0x37;
int i;
for(i = 7; 0 <= i; i --)
printf("%d\n", (byte >> i) & 0x01);
return 0;
}
Вы также можете использовать битовые поля, чтобы сделать это. Плохая часть бит-полей заключается в том, что именно то, как они работают, зависит от компилятора, но если вам не нужно переносить свой код на многие архитектуры, возможно, это нормально.
Вот пример, написанный на компьютере Ubuntu Linux и протестированный с помощью 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;
}
Объединение существует, поэтому мы можем получить к нему доступ в виде полного байта или получить доступ к нему по битовым полям. #pragma pack(1)
, чтобы убедиться, что битовые поля упали до байта, без лишних бит «заполнения». (Как я уже говорил, вы полагаетесь на детали реализации, когда используете битовые поля.)
Но посмотрите, насколько простым и чистым является доступ к битам, которые вы хотите. Вы можете записать в целом байт и зачитать нужные вам биты или записать в нужные вам биты и зачитать весь байт.
Если вы собираетесь использовать такой код, всегда полезно иметь некоторые утверждения, которые гарантируют его работу.
Если вы не собираетесь использовать бит-поля, я предлагаю вам определить функцию, которая выполняет ваши смены и маскировку, чтобы вы не испортили. Может быть, что-то вроде этого:
#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];
}
Вы передаете в значении, то какое бита позицию, которую вы хотите биты от, и сколько бита вы хотите. Таким образом, чтобы захватить 6 бит, начиная с битовой позиции 2, с тестовым значением 0x71 можно назвать:
x = bits(0x71, 2, 6); // x is set to 0x1c
Если вам не нравится, таблицы поиска, и вы хотите, мельчайший код, чтобы сделать это, вам можно использовать:
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));
}
Вы должны убедиться, что биты масок объявляются unsigned
, потому что если они будут подписаны, операция сдвига вправо подпишет-расширятся.
Если вы объявите эту последнюю версию функции как встроенную, поместите ее в заголовочные файлы и вызовите ее с постоянными значениями для i_bit
и c_bits
, она скомпилирует до минимального кода для решения проблемы. (Например, если i_bit
равно 0, компилятор знает, что >> 0
ничего не делает и просто не сгенерирует этот код. И если компилятор знает c_bits
как константу, он может выполнять всю работу смены mask_bits
во время компиляции.) Но вам нужно убедиться, что вы используете версию assert()
, которая не компилируется в вашей сборке релизов, а также использует собственный макрос ASSERT()
и не скомбинирует макрос.
Это самый простой функции использовать, я не хочу, чтобы другие бороться в течение длительного времени, прежде чем получить что-то похожее на это -
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);
Надежда это помогает кому-то в будущем
- 1. Доступ к битам в символе?
- 2. MIPS - доступ к отдельным битам
- 3. Доступ к нескольким битам в битах
- 4. C: Доступ к отдельным битам в номере uint16_t?
- 5. Доступ к определенным битам доступа Verilog
- 6. доступ к конкретным битам компонентов NSMutableArray
- 7. Определить союз, который может получить доступ к битам, грызет, байты
- 8. доступ к элементам char *
- 9. Биты в C, как мне получить доступ к базовым битам в C-поплавке?
- 10. Как получить доступ к битам в отображаемой памяти?
- 11. char * к строке в C#
- 12. C++ - Доступ к char * with & String [0] в классе
- 13. Доступ к указателю char в структуре C++ и выделение памяти
- 14. Есть ли способ доступа к отдельным битам с объединением?
- 15. C - Char к гексу
- 16. static char * vs static char [] доступ к памяти
- 17. Доступ к элементу массива с Char
- 18. Беззнаковый бит для доступа к битам, чтобы определить, содержит ли char состоящий из 1s и 0s
- 19. Чтение и запись по битам в C++ для кодировки Хаффмана
- 20. конвертировать char * в char? C++
- 21. c сплит char * в char **
- 22. C Преобразование char в char *
- 23. запись битам в двоичный файл в VB.Net
- 24. применить контрольную сумму в c к char
- 25. Добавление двоеточия (:) к unsigned char в C++
- 26. C++ не доступ к методу в ifstatement
- 27. Как получить доступ к объединению в C
- 28. Доступ к 3D-массиву в C++
- 29. Значение `pop` при обращении к битам
- 30. Доступ к переменной структуры в C++?
Здесь я предполагал, что вы хотите изолировать 11 от «0011». Если вам нужны только два младших бита, x & 0x03 будет работать, как показал dasblinkenlight. – zje