비트를 어떻게 설정하고 지우고 토글합니까?
답변
비트 설정
비트 OR 연산자 ( |
)를 사용하여 비트 를 설정하십시오.
number |= 1UL << n;
의 n
비트 가 설정됩니다 number
. st 비트 n
를 설정하려면 1
up 을 0 n-1
으로 설정하고 n
th 비트 를 설정하려면
보다 넓은 1ULL
경우 사용 ; 의 너비 이상으로 이동하는 정의되지 않은 동작이 어디인지 평가 한 후에야 프로모션이 진행 됩니다. 나머지 모든 예제에도 동일하게 적용됩니다.number
unsigned long
1UL << n
1UL << n
long
조금 지우기
비트 AND 연산자 ( &
)를 사용하여 비트 를 지 웁니다.
number &= ~(1UL << n);
그것의 n
th 비트를 취소합니다 number
. 비트 NOT 연산자 ( ~
)를 사용하여 비트 문자열을 반전 한 다음 AND해야합니다.
조금 토글
XOR 연산자 ( ^
)를 사용하여 비트를 토글 할 수 있습니다.
number ^= 1UL << n;
의 n
th 비트를 토글합니다 number
.
조금 확인
당신은 이것을 요구하지 않았지만 나는 그것을 추가 할 수도 있습니다.
비트를 확인하려면 숫자 n을 오른쪽으로 이동 한 다음 비트 AND로 이동하십시오.
bit = (number >> n) & 1U;
그것은 n
th 비트의 값을 number
변수 에 넣을 것입니다 bit
.
n 번째 비트를 x로 변경
2의 보수 C ++ 구현에서 다음과 같이 n
th 비트를 설정 1
하거나 0
달성 할 수 있습니다.
number ^= (-x ^ number) & (1UL << n);
비트는 n
경우 설정 될 것 x
입니다 1
, 그리고 경우 삭제 x
입니다 0
. x
다른 가치가 있다면 쓰레기가 생깁니다. x = !!x
0 또는 1로 부울합니다.
이것을 2의 보수 부정 행위 ( -1
1의 보수 또는 부호 / 크기 C ++ 구현과는 달리 모든 비트가 설정되어 있음)와 독립적으로 만들려면 부호없는 부정을 사용하십시오.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
또는
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
휴대용 비트 조작에 부호없는 유형을 사용하는 것이 일반적으로 좋습니다.
또는
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
맑은 것 n
번째 비트를하고 (x << n)
설정된 것 n
에 번째 비트를 x
.
일반적으로 코드를 복사 / 붙여 넣기하지 않는 것이 좋으며, 많은 사람들이 프리 프로세서 매크로 ( 커뮤니티 Wiki의 답변 아래로 ) 또는 캡슐화를 사용합니다.
답변
표준 C ++ 라이브러리 사용 : std::bitset<N>
.
또는 부스트 버전 : boost::dynamic_bitset
.
자신의 것을 굴릴 필요가 없습니다.
#include <bitset>
#include <iostream>
int main()
{
std::bitset<5> x;
x[1] = 1;
x[2] = 0;
// Note x[0-4] valid
std::cout << x << std::endl;
}
[Alpha:] > ./a.out
00010
Boost 버전은 표준 라이브러리 컴파일 타임 크기 비트 세트와 비교하여 런타임 크기 비트 세트를 허용합니다 .
답변
다른 옵션은 비트 필드를 사용하는 것입니다.
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
3 비트 필드를 정의합니다 (실제로 3 비트의 1 비트 필드). 비트 작업이 이제 조금 더 간단 해졌습니다 (haha).
비트를 설정하거나 지우려면 :
mybits.b = 1;
mybits.c = 0;
비트를 토글하려면 :
mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1; /* all work */
조금 확인 :
if (mybits.c) //if mybits.c is non zero the next line below will execute
이것은 고정 크기 비트 필드에서만 작동합니다. 그렇지 않으면 이전 게시물에서 설명한 비트 트위들 링 기술에 의존해야합니다.
답변
비트 파일을 처리하고 지우기 위해 헤더 파일에 정의 된 매크로를 사용합니다.
/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b)))) // '!!' to make sure this returns 0 or 1
/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK_ALL(x,y) (((x) & (y)) == (y)) // warning: evaluates y twice
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))
답변
때때로 비트 이름enum
을 지정 하기 위해를 사용하는 것이 좋습니다 :
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
그런 다음 나중에 이름을 사용하십시오 . 즉 쓰기
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
설정하고 지우고 테스트합니다. 이 방법으로 나머지 코드에서 마법의 숫자를 숨길 수 있습니다.
그 외에는 Jeremy의 솔루션을 보증합니다.
답변
에서 snip-c.zip 의 bitops.h :
/*
** Bit set, clear, and test operations
**
** public domain snippet by Bob Stout
*/
typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;
#define BOOL(x) (!(!(x)))
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
좋아, 물건을 분석하자 …
이들 모두에서 문제가있는 것으로 보이는 일반적인 표현은 “(1L << (posn))”입니다. 이 모든 작업은 단일 비트를 사용하는 마스크를 만들고 모든 정수 유형에서 작동합니다. “posn”인수는 비트를 원하는 위치를 지정합니다. posn == 0이면이 표현식은 다음과 같이 평가됩니다.
0000 0000 0000 0000 0000 0000 0000 0001 binary.
posn == 8이면 다음과 같이 평가됩니다.
0000 0000 0000 0000 0000 0001 0000 0000 binary.
즉, 단순히 지정된 위치에 1을 가진 0의 필드를 만듭니다. 까다로운 부분은 BitClr () 매크로에 있으며 1의 필드에 단일 0 비트를 설정해야합니다. 이는 물결표 (~) 연산자로 표시된 것과 동일한 식의 1의 보수를 사용하여 수행됩니다.
마스크가 만들어지면 비트 단위 및 (&) 또는 (|) 및 xor (^) 연산자를 사용하여 제안한대로 인수에 적용됩니다. 마스크는 long 유형이므로 매크로는 char, short, int 또는 long에서 잘 작동합니다.
결론은 이것이 모든 종류의 문제에 대한 일반적인 해결책이라는 것입니다. 물론 필요할 때마다 명시 적 마스크 값을 사용하여 이러한 매크로에 해당하는 내용을 다시 작성하는 것이 가능하고 적절합니다. 매크로 대체는 전 처리기에서 발생하므로 생성 된 코드는 컴파일러가 값을 일정하게 간주한다는 사실을 반영합니다. 즉, 일반화 된 매크로를 사용하여 필요할 때마다 “바퀴를 재창조”하는 것만 큼 효율적입니다. 비트 조작을하십시오.
확신이 없습니까? 테스트 코드는 다음과 같습니다. Watcom C를 완전히 최적화하고 _cdecl을 사용하지 않고 결과 분해가 가능한 한 깨끗해졌습니다.
—- [TEST.C] —————————————– ———————–
#define BOOL(x) (!(!(x)))
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
int bitmanip(int word)
{
word = BitSet(word, 2);
word = BitSet(word, 7);
word = BitClr(word, 3);
word = BitFlp(word, 9);
return word;
}
—- [TEST.OUT (분해)] ————————————– ———
Module: C:\BINK\tst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
Segment: _TEXT BYTE 00000008 bytes
0000 0c 84 bitmanip_ or al,84H ; set bits 2 and 7
0002 80 f4 02 xor ah,02H ; flip bit 9 of EAX (bit 1 of AH)
0005 24 f7 and al,0f7H
0007 c3 ret
No disassembly errors
—- [finis] ——————————————- ———————-
답변
비트 연산자를 사용하십시오. &
|
마지막 비트를 설정하려면 000b
:
foo = foo | 001b
마지막 비트를 확인하려면 foo
:
if ( foo & 001b ) ....
마지막 비트를 지우려면 foo
:
foo = foo & 110b
나는 XXXb
명확성을 위해 사용 했다. 비트를 패킹하는 데이터 구조에 따라 HEX 표현으로 작업하고있을 것입니다.