programing

C에서 32비트 부호 없는 정수의 특정 'n' 비트를 어떻게 추출합니까?

elecom 2023. 6. 22. 21:27
반응형

C에서 32비트 부호 없는 정수의 특정 'n' 비트를 어떻게 추출합니까?

C의 32비트 부호 없는 정수에서 'n'개의 특정 비트를 추출하는 방법에 대해 알려줄 수 있는 사람이 있습니까?

예를 들어 32비트 값의 처음 17비트를 원한다고 가정하면 어떻게 해야 합니까?
연산자를 해 보고 를 는저제계비연사비용한가생다야각으로 얻을 수 .

unsigned last8bitsvalue=(32 bit integer) % 16
unsigned last16bitsvalue=(32 bit integer) % 32

이거 맞는건가요?이것을 하는 더 좋고 효율적인 방법이 있습니까?

저는 그것을 '추출'이라고 생각하는 대신에, 그것을 '격리'라고 생각하는 것을 좋아합니다.원하는 비트가 분리되면 원하는 비트를 사용할 수 있습니다.

비트 집합을 분리하려면 AND 마스크를 적용합니다.

값의 마지막 X 비트를 원하는 경우 사용할 수 있는 간단한 트릭이 있습니다.

unsigned  mask;
mask = (1 << X) - 1;
lastXbits = value & mask;

'startBit'에서 시작하는 'value' 중간에 X비트 실행을 분리하려면...

unsigned  mask;
mask = ((1 << X) - 1) << startBit;
isolatedXbits = value & mask;

이게 도움이 되길 바랍니다.

하려면 먼저 n비트 마스크를 만들 수 .AND원하는 비트를 얻기 위해 번호와 함께 사용합니다.

비트 a에서 비트 b까지 마스크를 만드는 간단한 기능.

unsigned createMask(unsigned a, unsigned b)
{
   unsigned r = 0;
   for (unsigned i=a; i<=b; i++)
       r |= 1 << i;

   return r;
}

당신은 그것을 확인해야 합니다 <=b.

(AND) 비 12~16 을면다를함수논호다 & (논리 AND)r당신의 번호로N

r = createMask(12,16);
unsigned result = r & N;

원하는 경우 결과를 변경할 수 있습니다.이것이 도움이 되길 바랍니다.

bit (을 작업을 , 제가 에는 modulus는 bottom bit (단순히)을 구하는 작업을 합니다.value & 0x1ffff는 보직적하 "단비 17트를"보다 "를 더 표현합니다.value % 131072그래서 그렇게 하는 것이 더 이해하기 쉽습니다.

는 32비트 트부없비는 17비트 습같다입니다.value & 0xffff8000(만약 당신이 그들이 여전히 그들의 위치에 있기를 원한다면), 또는.value >> 15결과의 하위 17비트에 있는 값의 상위 17비트를 원하는 경우.

Intel 및 AMD CPU와 ARM에는 단일 BEXTR(비트 필드 추출(레지스터 포함) x86 명령이 있습니다.이 명령을 명시적으로 호출할 수 있는 (link requires sign-in)와 같이 명시적으로 호출할 수 있습니다.

은 그은실니다행합을 합니다.(source >> offset) & ((1 << n) - 1) 코드: get C 코드: 가기오져n의 연속 비트source에서시여하에서 offset다음은 에지 케이스를 처리하는 완전한 함수 정의입니다.

#include <limits.h>

unsigned getbits(unsigned value, unsigned offset, unsigned n)
{
  const unsigned max_n = CHAR_BIT * sizeof(unsigned);
  if (offset >= max_n)
    return 0; /* value is padded with infinite zeros on the left */
  value >>= offset; /* drop offset bits */
  if (n >= max_n)
    return value; /* all  bits requested */
  const unsigned mask = (1u << n) - 1; /* n '1's */
  return value & mask;
}

예를 들어, 다음과 같은 경우3에서 조금 떨어진.2273(0b100011100001합니다.5 -트호, 출비getbits(2273, 5, 3)을 추출합니다7을 추니다합출(다니▁—합—0b111).

예를 들어 32비트 값의 처음 17비트를 원한다고 가정하면 어떻게 해야 합니까?

unsigned first_bits = value & ((1u << 17) - 1); // & 0x1ffff

을 가정하여CHAR_BIT * sizeof(unsigned)시스템에 32가 있습니다.

모듈러스 연산자를 사용해야 한다고 생각합니다. 사용해보고 마지막 8비트와 마지막 16비트를 얻을 수 있었습니다.

unsigned last8bitsvalue  = value & ((1u <<  8) - 1); // & 0xff
unsigned last16bitsvalue = value & ((1u << 16) - 1); // & 0xffff

질문의 모든 예제에서와 같이 오프셋이 항상 0이면 더 일반적일 필요가 없습니다.getbits()마스크를 계산하는 데 도움이 되는 특별한 CPU 명령 BLSMSK가 있습니다.

정수의 마지막 X 비트가 필요한 경우 이진 마스크를 사용합니다.

unsigned last8bitsvalue=(32 bit integer) & 0xFF
unsigned last16bitsvalue=(32 bit integer) & 0xFFFF

이것은 허용된 답변의 간략한 변형입니다. 아래 함수는 비트 마스크를 만들어 ~에서 ~로 비트를 추출합니다.원래 숫자에 AND 로직을 적용한 후에는 결과가 이동되어 추출된 비트만 반환됩니다.명확성을 위해 색인/ 무결성 검사를 건너뜁니다.

uint16_t extractInt(uint16_t orig16BitWord, unsigned from, unsigned to) 
{
  unsigned mask = ( (1<<(to-from+1))-1) << from;
  return (orig16BitWord & mask) >> from;
}

추출할 비트가 정확히 설정된 마스크가 있는 정수를 비트 단위로 지정됩니다.그런 다음 원하는 경우 결과를 오른쪽으로 이동하여 추출된 비트의 위치를 변경합니다.

unsigned int lowest_17_bits = myuint32 & 0x1FFFF;
unsigned int highest_17_bits = (myuint32 & (0x1FFFF << (32 - 17))) >> (32 - 17);

편집: 후자는 가장 높은 17비트를 가장 낮은 17비트로 재배치합니다. 이는 더 큰 "내"에서 정수를 추출해야 할 경우 유용합니다.시프트는 할 수 .>>)이(가 하지 않을 경우 이 옵션을 선택합니다.

#define GENERAL__GET_BITS_FROM_U8(source,lsb,msb) \
    ((uint8_t)((source) & \
        ((uint8_t)(((uint8_t)(0xFF >> ((uint8_t)(7-((uint8_t)(msb) & 7))))) & \
             ((uint8_t)(0xFF << ((uint8_t)(lsb) & 7)))))))

#define GENERAL__GET_BITS_FROM_U16(source,lsb,msb) \
    ((uint16_t)((source) & \
        ((uint16_t)(((uint16_t)(0xFFFF >> ((uint8_t)(15-((uint8_t)(msb) & 15))))) & \
            ((uint16_t)(0xFFFF << ((uint8_t)(lsb) & 15)))))))

#define GENERAL__GET_BITS_FROM_U32(source,lsb,msb) \
    ((uint32_t)((source) & \
        ((uint32_t)(((uint32_t)(0xFFFFFFFF >> ((uint8_t)(31-((uint8_t)(msb) & 31))))) & \
            ((uint32_t)(0xFFFFFFFF << ((uint8_t)(lsb) & 31)))))))
int get_nbits(int num, int n)
{
return  (((1<<n)-1) & num);
}

이것을 달성하기 위한 다른 방법이 있습니다.를 사용할 수 있습니다.union 필드를 struct.

예:

typedef thesebits
{

  unsigned long first4    : 4;
  unsigned long second4   : 4;
  unsigned long third8    : 8;
  unsigned long forth7    : 7;
  unsigned long fifth3    : 3;
  unsigned long sixth5    : 5;
  unsigned long last1     : 1;

} thesebits;

은 그것을 할 수 .struct원하는 비트 패턴에 도달할 수 있습니다.비트 패턴이 여러 개인 경우 조합에서도 사용할 수 있습니다.

typedef thesebitstwo
{

  unsigned long first8    : 8;
  unsigned long second8   : 8;
  unsigned long third8    : 8;
  unsigned long last8     : 8;

} thesebitstwo;

이제 조합을 설정할 수 있습니다.

typedef union myunion 
{
   unsigned long mynumber;
   thesebits     mybits;
   thesebitstwo  mybitstwo;
} myunion;

그런 다음 회원에게 내 번호를 할당하는 임의의 번호에서 원하는 비트에 액세스할 수 있습니다.

myunion getmybits;
getmybits.mynumber = 1234567890;

마지막 8비트를 원하는 경우:

last16bits = getmybits.mybitstwo.last8;

두 번째 4비트를 원하는 경우:

second4bits = getmybits.mybits.second4;

저는 무작위로 할당된 다른 비트들을 보여주기 위해 두 가지 예를 제시했습니다.원하는 비트에 대해 구조 비트 필드를 설정할 수 있습니다.는 모든 을 모든 변 만 다 습 니 었 들 유 을 형unsigned long그러나 비트 수가 유형에 사용할 수 있는 비트 수를 초과하지 않는 한 모든 변수 유형을 사용할 수 있습니다.그래서 이것들의 대부분은 단지unsigned int그리고 어떤 사람들은 심지어unsigned short

여기서 주의할 점은 항상 동일한 비트 집합을 반복적으로 원할 경우 이 기능이 작동한다는 것입니다.보고 있는 비트를 변경해야 하는 이유가 있다면 다음과 같은 비트 복사본을 보관하는 배열을 가진 구조를 사용할 수 있습니다.

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

typedef struct bits32
{

    bool b0              : 1;
    bool b1              : 1;
    bool b2              : 1;
    bool b3              : 1;
    bool b4              : 1;
    bool b5              : 1;
    bool b6              : 1;
    bool b7              : 1;
    bool b8              : 1;    
    bool b9              : 1;
    bool b10             : 1;
    bool b11             : 1;
    bool b12             : 1;    
    bool b13             : 1;
    bool b14             : 1;
    bool b15             : 1;
    bool b16             : 1;    
    bool b17             : 1;
    bool b18             : 1;
    bool b19             : 1;
    bool b20             : 1;    
    bool b21             : 1;
    bool b22             : 1;
    bool b23             : 1;
    bool b24             : 1;    
    bool b25             : 1;
    bool b26             : 1;
    bool b27             : 1;
    bool b28             : 1;    
    bool b29             : 1;
    bool b30             : 1;
    bool b31             : 1;

} bits32;

typedef struct flags32 {
    union 
    {
    
        uint32_t        number;
        struct bits32   bits;
    
    };
    bool                    b[32];
} flags32;

struct flags32 assignarray ( unsigned long thisnumber )
{
    struct flags32  f;
    f.number = thisnumber;
    
    f.b[0] = f.bits.b0;
    f.b[1] = f.bits.b1;
    f.b[2] = f.bits.b2;
    f.b[3] = f.bits.b3;
    f.b[4] = f.bits.b4;
    f.b[5] = f.bits.b5;
    f.b[6] = f.bits.b6;
    f.b[7] = f.bits.b7;
    f.b[8] = f.bits.b8;
    f.b[9] = f.bits.b9;
    f.b[10] = f.bits.b10;
    f.b[11] = f.bits.b11;
    f.b[12] = f.bits.b12;
    f.b[13] = f.bits.b13;
    f.b[14] = f.bits.b14;
    f.b[15] = f.bits.b15;
    f.b[16] = f.bits.b16;
    f.b[17] = f.bits.b17;
    f.b[18] = f.bits.b18;
    f.b[19] = f.bits.b19;
    f.b[20] = f.bits.b20;
    f.b[21] = f.bits.b21;
    f.b[22] = f.bits.b22;
    f.b[23] = f.bits.b23;
    f.b[24] = f.bits.b24;
    f.b[25] = f.bits.b25;
    f.b[26] = f.bits.b26;
    f.b[27] = f.bits.b27;
    f.b[28] = f.bits.b28;
    f.b[29] = f.bits.b29;
    f.b[30] = f.bits.b30;
    f.b[31] = f.bits.b31;

    return f;
    
}

int main ()

{

    struct flags32 bitmaster;
    bitmaster = assignarray(1234567890);

    printf("%d\n", bitmaster.number);
    printf("%d\n",bitmaster.bits.b9);
    printf("%d\n",bitmaster.b[9]);
    
    printf("%lu\n", sizeof(bitmaster));
    printf("%lu\n", sizeof(bitmaster.number));
    printf("%lu\n", sizeof(bitmaster.bits));
    printf("%lu\n", sizeof(bitmaster.b));
    
}

이 마지막 예제의 문제는 압축되지 않았다는 것입니다.유니언 자체는 4바이트에 불과하지만 비트 필드에 대한 포인터를 할 수 없기 때문에(복잡하고 논쟁의 여지가 없는 "비표준" 코드 없이) 어레이는 각 부울 값의 복사본을 만들고 비트 대신 각 값에 대해 전체 바이트를 사용하므로 총 메모리 공간이 9배가 됩니다(제가 제시한 printf 문 예제를 실행하면,두고 보세요).

그러나 이제 각 비트를 하나씩 지정하고 변수를 사용하여 각 비트를 인덱싱할 수 있습니다. 메모리가 부족하지 않은 경우에는 매우 유용합니다.

와 "typedefs"를 .assignarray 하는을할의 로서의 기능flags32여러 변수로 쉽게 확장할 수 있습니다.를 사용할 수 없다면 을 .b#으로 정의하면 .flags32나머지 구조는 생략합니다.그러면 당신은 또한 필요하지 않습니다.assignarray기능을 사용하면 훨씬 적은 메모리를 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/8011700/how-do-i-extract-specific-n-bits-of-a-32-bit-unsigned-integer-in-c

반응형