[c] C의 정수 값에서 비트 단위 데이터를 얻으려면 어떻게해야합니까?

십진수 비트를 추출하고 싶습니다.

예를 들어 7은 이진 0111이고 bool에 저장된 모든 비트를 111 1 1 얻고 싶습니다. 어떻게 할 수 있습니까?

좋습니다. 루프는 좋은 옵션이 아닙니다. 다른 작업을 수행 할 수 있습니까?



답변

n의 k 번째 비트를 원한다면 다음을 수행하십시오.

(n & ( 1 << k )) >> k

여기에서 마스크를 만들고 마스크를 n에 적용한 다음 마스크 된 값을 오른쪽으로 이동하여 원하는 비트를 얻습니다. 다음과 같이 더 완전하게 작성할 수 있습니다.

    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;

여기에서 비트 마스킹에 대한 자세한 내용을 읽을 수 있습니다 .

다음은 프로그램입니다.

#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");
}


답변

요청에 따라 집게 손가락의 대답에 대한 의견을 본격적인 대답으로 확장하기로 결정했습니다. 그의 대답은 맞지만 불필요하게 복잡하다. 또한 모든 현재 답변은 부호있는를 사용 int하여 값을 나타냅니다. 음수 값의 오른쪽 이동은 구현에 따라 정의되고 (즉, 이식 가능하지 않음) 왼쪽 이동으로 인해 정의되지 않은 동작 발생할 수 있으므로 위험합니다 ( 이 질문 참조 ).

원하는 비트를 최하위 비트 위치로 오른쪽 시프트하면을 사용하여 마스킹을 수행 할 수 있습니다 1. 각 비트에 대해 새 마스크 값을 계산할 필요가 없습니다.

(n >> k) & 1

완전한 프로그램으로서, 단일 비트 값의 배열을 계산하고 인쇄합니다.

#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);
}

이 경우 특정 비트가 아닌 모든 비트를 계산한다고 가정하면 루프를 다음과 같이 추가로 변경할 수 있습니다.

for(bit = 0; bit < n_bits; ++bit, input >>= 1)
    bits[bit] = input & 1;

이는 input제자리에서 수정 되어 일정한 폭의 단일 비트 시프트를 사용할 수있게하여 일부 아키텍처에서 더 효율적일 수 있습니다.


답변

이를 수행하는 한 가지 방법이 있습니다. 다른 많은 방법이 있습니다.

bool b[4];
int v = 7;  // number to dissect

for (int j = 0;  j < 4;  ++j)
   b [j] =  0 != (v & (1 << j));

루프 사용이 바람직하지 않은 이유를 이해하기는 어렵지만 루프를 펼치는 것은 쉽습니다.

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));

또는 마지막 네 개의 문에서 상수 표현식을 평가합니다.

b [0] =  0 != (v & 1);
b [1] =  0 != (v & 2);
b [2] =  0 != (v & 4);
b [3] =  0 != (v & 8);


답변

여기에 아주 간단한 방법이 있습니다.

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;
}


답변

@prateek 당신의 도움에 감사드립니다. 프로그램에서 사용하기 위해 주석으로 함수를 다시 작성했습니다. 비트를 늘리려면 8을 늘립니다 (정수는 최대 32).

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;
}


답변

루프를 원하지 않으면 작성해야합니다.

#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;
}

여기에 설명 된대로 이니셜 라이저에서도 작동합니다.


답변

#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;
}