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
'programing' 카테고리의 다른 글
| 모든 원격 Git 분기를 로컬 분기로 추적 (0) | 2023.06.22 |
|---|---|
| NA를 최신 비NA 값으로 대체 (0) | 2023.06.22 |
| Git 브랜치를 자체 저장소로 이동하려면 어떻게 해야 합니까? (0) | 2023.06.22 |
| 왜 malloc()와 printf()가 비재입국으로 언급됩니까? (0) | 2023.06.22 |
| 파이썬 내에서 간단한 "chmod +x"를 어떻게 하나요? (0) | 2023.06.22 |