Câu trả lời:
Nếu bạn muốn bit thứ k của n, thì làm
(n & ( 1 << k )) >> k
Ở đây chúng ta tạo một mặt nạ, áp dụng mặt nạ cho n, và sau đó dịch sang phải giá trị mặt nạ để chỉ nhận được bit chúng ta muốn. Chúng tôi có thể viết nó ra đầy đủ hơn như:
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
Bạn có thể đọc thêm về bit-mask tại đây .
Đây là một chương trình:
#include <stdio.h>
#include <stdlib.h>
int *get_bits(int n, int bitswanted){
int *bits = malloc(sizeof(int) * bitswanted);
int k;
for(k=0; k<bitswanted; k++){
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
bits[k] = thebit;
}
return bits;
}
int main(){
int n=7;
int bitswanted = 5;
int *bits = get_bits(n, bitswanted);
printf("%d = ", n);
int i;
for(i=bitswanted-1; i>=0;i--){
printf("%d ", bits[i]);
}
printf("\n");
}
struct
cũng có thể hữu ích, vì bạn nhận được tất cả dữ liệu cần thiết chỉ với một thao tác.
Theo yêu cầu, tôi quyết định mở rộng bình luận của mình về câu trả lời của ngón trỏ thành một câu trả lời chính thức. Mặc dù câu trả lời của anh ấy là đúng, nhưng nó không cần thiết phải phức tạp. Hơn nữa, tất cả các câu trả lời hiện tại đều sử dụng dấu int
s để đại diện cho các giá trị. Điều này rất nguy hiểm, vì dịch chuyển sang phải của các giá trị âm được xác định bởi việc triển khai (nghĩa là không di động) và dịch chuyển sang trái có thể dẫn đến hành vi không xác định (xem câu hỏi này ).
Bằng cách chuyển sang phải bit mong muốn sang vị trí bit ít quan trọng nhất, có thể thực hiện việc che dấu 1
. Không cần tính giá trị mặt nạ mới cho mỗi bit.
(n >> k) & 1
Là một chương trình hoàn chỉnh, tính toán (và sau đó in) một mảng các giá trị bit đơn:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned
input = 0b0111u,
n_bits = 4u,
*bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
bit = 0;
for(bit = 0; bit < n_bits; ++bit)
bits[bit] = (input >> bit) & 1;
for(bit = n_bits; bit--;)
printf("%u", bits[bit]);
printf("\n");
free(bits);
}
Giả sử rằng bạn muốn tính toán tất cả các bit như trong trường hợp này, chứ không phải một bit cụ thể, vòng lặp có thể được thay đổi thêm thành
for(bit = 0; bit < n_bits; ++bit, input >>= 1)
bits[bit] = input & 1;
Điều này sửa đổi input
tại chỗ và do đó cho phép sử dụng độ rộng không đổi, dịch chuyển bit đơn, có thể hiệu quả hơn trên một số kiến trúc.
Đây là một cách để làm điều đó — còn nhiều cách khác:
bool b[4];
int v = 7; // number to dissect
for (int j = 0; j < 4; ++j)
b [j] = 0 != (v & (1 << j));
Thật khó hiểu tại sao việc sử dụng vòng lặp lại không được mong muốn, nhưng có thể dễ dàng gỡ bỏ vòng lặp:
bool b[4];
int v = 7; // number to dissect
b [0] = 0 != (v & (1 << 0));
b [1] = 0 != (v & (1 << 1));
b [2] = 0 != (v & (1 << 2));
b [3] = 0 != (v & (1 << 3));
Hoặc đánh giá các biểu thức hằng trong bốn câu lệnh cuối cùng:
b [0] = 0 != (v & 1);
b [1] = 0 != (v & 2);
b [2] = 0 != (v & 4);
b [3] = 0 != (v & 8);
@prateek cảm ơn bạn đã giúp đỡ. Tôi đã viết lại hàm với các chú thích để sử dụng trong một chương trình. Tăng 8 cho nhiều bit hơn (lên đến 32 cho một số nguyên).
std::vector <bool> bits_from_int (int integer) // discern which bits of PLC codes are true
{
std::vector <bool> bool_bits;
// continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
for (int i = 0; i < 8; i++)
{
bool_bits.push_back (integer%2); // remainder of dividing by 2
integer /= 2; // integer equals itself divided by 2
}
return bool_bits;
}
Nếu bạn không muốn bất kỳ vòng lặp nào, bạn sẽ phải viết nó ra:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 7;
#if 0
bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
#else
#define BTB(v,i) ((v) & (1u << (i))) ? true : false
bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
#undef BTB
#endif
printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);
return 0;
}
Như đã trình bày ở đây, điều này cũng hoạt động trong trình khởi tạo.
Sử dụng std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
(n >> k) & 1
có giá trị như nhau và không yêu cầu tính toán mặt nạ vì mặt nạ không đổi do dịch chuyển trước khi tạo mặt nạ thay vì ngược lại.