Tôi có một số hex 0x37 và biểu diễn nhị phân của nó là 0011 0111. Làm cách nào để truy cập 2 bit đầu tiên của biểu diễn nhị phân là "11"? Làm thế nào để sử dụng bit shifting hoặc masking để đạt được điều này? Tôi có thể truy cập từng chút một nhưng không thể truy cập từng bit một?Truy cập các bit trong một char trong C
Trả lời
Nếu bạn &
số của mình với 0x03, bạn sẽ nhận được hai bit cuối cùng.
char c = 0x37;
char mask = 0x03;
char lastTwo = c & mask;
Đặt cược tốt nhất của bạn là sử dụng mặt nạ bit như bạn đã đề cập. Something như thế này nên làm như lừa:
x = 0x37;
y = x&0x30; //Mask out the first two bits of the higher nibble
y = y>>4;
Đây là một mẫu truy cập vào nó từng chút một:
#include <stdio.h>
int main()
{
char byte = 0x37;
int i;
for(i = 7; 0 <= i; i --)
printf("%d\n", (byte >> i) & 0x01);
return 0;
}
Bạn cũng có thể sử dụng bit lĩnh vực để làm điều này. Phần xấu về các trường bit là chính xác cách chúng hoạt động có phần phụ thuộc vào trình biên dịch, nhưng nếu bạn không cần phải chuyển mã của mình sang nhiều kiến trúc, có lẽ nó là tốt.
Dưới đây là một ví dụ, được viết trên máy tính Ubuntu Linux và được kiểm tra bằng 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;
}
Công đoàn ở đó để chúng tôi có thể truy cập dưới dạng byte đầy đủ hoặc truy cập theo trường bit. #pragma pack(1)
là có để đảm bảo rằng các trường bit đóng gói xuống một byte, không có thêm "đệm" bit trong đó. (Như tôi đã nói trước đây, bạn đang dựa vào chi tiết triển khai khi bạn sử dụng các trường bit.)
Nhưng hãy xem cách đơn giản và sạch sẽ là truy cập vào các bit bạn muốn. Bạn có thể viết toàn bộ một byte và đọc các bit bạn muốn, hoặc viết vào các bit bạn muốn và đọc toàn bộ byte.
Nếu bạn định sử dụng mã như thế này, bạn nên có một số lời khẳng định chắc chắn rằng nó hoạt động.
Nếu bạn không sử dụng các trường bit, tôi khuyên bạn nên xác định một chức năng mà dịch chuyển và che mặt cho bạn, để đảm bảo bạn không làm hỏng. Có thể một cái gì đó như thế này:
#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];
}
Bạn chuyển một giá trị, sau đó vị trí bit bạn muốn bit và số bit bạn muốn. Vì vậy, để lấy 6 bit bắt đầu từ vị trí bit 2, với một giá trị thử nghiệm của 0x71 bạn có thể gọi:
x = bits(0x71, 2, 6); // x is set to 0x1c
Nếu bạn không thích các bảng tra cứu, và bạn muốn mã nhỏ nhất để làm điều này, bạn có thể sử dụng:
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));
}
Bạn cần phải chắc chắn rằng các bit mặt nạ được khai báo unsigned
bởi vì nếu họ được ký kết, các hoạt động phải thay đổi sẽ tiến hành ký-mở rộng.
Nếu bạn khai báo phiên bản mới nhất của hàm là nội tuyến, hãy đặt nó vào tệp tiêu đề và gọi nó với giá trị không đổi cho i_bit
và c_bits
, nó sẽ biên dịch xuống mã tối thiểu để giải quyết vấn đề. (Ví dụ, nếu i_bit
là 0, trình biên dịch biết rằng >> 0
không làm bất cứ điều gì và sẽ không tạo ra mã đó.Và nếu trình biên dịch biết c_bits
là hằng số, nó có thể thực hiện tất cả công việc dịch mask_bits
tại thời gian biên dịch.) Nhưng bạn sẽ cần phải đảm bảo rằng bạn đang sử dụng phiên bản assert()
để biên dịch thành không có gì trong bản phát hành bản phát hành của bạn hoặc sử dụng macro ASSERT()
của riêng bạn và làm cho macro của bạn biên dịch thành không có gì.
Đây là chức năng dễ sử dụng nhất, tôi không muốn người khác gặp khó khăn trong một thời gian dài trước khi nhận được một cái gì đó tương tự như sau -
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);
Hy vọng nó sẽ giúp ai đó trong tương lai
- 1. char ** vs char * c [] để truy cập mảng chuỗi
- 2. Nhận số bit trong char
- 3. Làm cách nào để truy cập vào bit dấu của một số trong C++?
- 4. Truy cập các tệp lớn trong C
- 5. Có cách nào để truy cập các bit riêng lẻ bằng công đoàn không?
- 6. Trong C++, về các kiểu chuyển dịch bit và đúc
- 7. Các trường bit trong Scala
- 8. Truy cập các lớp Matlab trong MEX/C-code
- 9. bit vectơ trong C++
- 10. Truy cập các file ngoài MAX_PATH trong C# /. NET
- 11. Truy cập các biến lớp tĩnh trong C++?
- 12. Truy cập các thành viên lớp C# trong IronPython
- 13. truy cập biến đồng thời trong c
- 14. C# Truy cập các đối tượng quản lý trong ManagementObjectCollection
- 15. Truy cập bộ nhớ nhanh trong C++?
- 16. Truy cập GMail bằng AE.Net.Mail trong C#
- 17. Xoay bit trong C
- 18. Truy cập Namespace Chánh trong C++
- 19. Cách một byte bộ nhớ được truy cập bởi CPU trong bộ nhớ 32 bit và bộ xử lý 32 bit
- 20. C++ truy cập các tiện ích con từ một hàm
- 21. thay đổi Bit trong C++
- 22. lập chỉ mục bit trong C?
- 23. SSIS Chuyển đổi một char thành boolean/bit
- 24. Unicode được lưu trữ trong C char
- 25. Có thể chuyển đổi char [] thành char * trong C?
- 26. C++ bản đồ <string, vector <char>> truy cập
- 27. Diffie-Hellman 1024 bit trong C#
- 28. Lưu trữ một số nguyên vào một char * trong C++
- 29. sizeof char * mảng trong C/C++
- 30. Độ lệch truy cập biến trong một dẫn xuất QObject
Ở đây, tôi giả sử bạn muốn cô lập 11 từ "0011". Nếu bạn chỉ cần hai bit thứ tự thấp nhất, x & 0x03 sẽ hoạt động, như dasblinkenlight đã hiển thị. – zje