Câu hỏi Làm thế nào để có được bit-by-bit dữ liệu từ một giá trị số nguyên trong C?


Tôi muốn trích xuất các bit của một số thập phân.

Ví dụ, 7 là số nhị phân 0111 và tôi muốn lấy 0 1 1 1 tất cả các bit được lưu trữ trong bool. Làm thế nào tôi có thể làm như vậy?

OK, một vòng lặp không phải là một lựa chọn tốt, tôi có thể làm điều gì khác cho việc này không?


76
2018-02-12 04:51


gốc




Các câu trả lời:


Nếu bạn muốn bit thứ k của n, thì hãy 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 đó phải thay đổi giá trị mặt nạ để có được chỉ là 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-masking đâ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");
}

120
2018-02-12 04:54



(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ạ là hằng số do chuyển dịch trước khi mặt nạ thay vì theo cách khác. - Joe
@ Joe bạn có thể giải thích rằng, có lẽ trong một câu trả lời, xin vui lòng? - Dan Rosenstark
@Yar đã mở rộng nhận xét của tôi một chút và thêm câu trả lời mới theo yêu cầu - Joe
Khi sử dụng các bit đã biết để biết thông tin (tức là đối với các giao thức mạng, chẳng hạn như Websockets), hãy truyền dữ liệu lên struct cũng có thể hữu ích khi bạn nhận được tất cả dữ liệu được yêu cầu với một thao tác đơn lẻ. - Myst
@forefinger, bạn có thể xin vui lòng gửi một ví dụ đầu ra của mã. - Ashish Ahuja


Theo yêu cầu, tôi quyết định mở rộng nhận xét của tôi về câu trả lời của người xếp hàng trước cho một câu trả lời chính thức. Mặc dù câu trả lời của ông là chính xác, nó là không cần thiết phức tạp. Hơn nữa tất cả các câu trả lời hiện tại sử dụng đã ký ints để biểu diễn các giá trị. Điều này là nguy hiểm, vì việc dịch chuyển đúng các giá trị âm được xác định thực hiện (nghĩa là không di chuyển) và dịch chuyển 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 dịch chuyển bit mong muốn vào vị trí bit ít quan trọng nhất, có thể thực hiện thao tác che bằng 1. Không cần tính toán giá trị mặt nạ mới cho từng 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, và không phải là 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 cố định, thay đổi một bit, có thể hiệu quả hơn trên một số kiến ​​trúc.


57
2017-10-07 07:16





Đây là một cách để làm điều đó - có 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));

3
2018-02-12 04:55





Đây là một cách rất đơn giản để làm điều đó;

int main()
{
    int s=7,l=1;
    vector <bool> v;
    v.clear();
    while (l <= 4)
    {
        v.push_back(s%2);
        s /= 2;
        l++;
    }
    for (l=(v.size()-1); l >= 0; l--)
    {
        cout<<v[l]<<" ";
    }
    return 0;
}

2
2018-02-12 05:02





@prateek cảm ơn bạn đã giúp đỡ của bạn. Tôi viết lại hàm bằng 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;
}

1
2018-02-24 18:52





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ư được minh họa ở đây, điều này cũng hoạt động trong một bộ khởi tạo.


1
2018-05-20 11:17





Sử dụng std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();

1
2018-05-12 14:47





#include <stdio.h>

int main(void)
{
    int number = 7; /* signed */
    int vbool[8 * sizeof(int)];
    int i;
        for (i = 0; i < 8 * sizeof(int); i++)
        {
            vbool[i] = number<<i < 0;   
            printf("%d", vbool[i]);
        }
    return 0;
}

0
2018-05-20 02:55