비트를 설정하고 지우고 토글하는 방법은 무엇입니까?
질문자 :JeffV
비트 설정
비트 OR 연산자( |
)를 사용하여 비트를 설정합니다.
number |= 1UL << n;
number
n
번째 비트가 설정됩니다. n
당신이 설정하려는 경우, 0이어야 1
개까지에 너무 번째 비트와 n-1
당신이 설정하려는 경우, n
번째 비트를.
number
unsigned long
보다 넓은 경우 1ULL
사용합니다. 촉진 1UL << n
평가할 때까지 일어나지 않는다 1UL << n
는 시프트 정의되지 않은 동작은 더의 폭보다 의해 어디 long
. 나머지 모든 예에도 동일하게 적용됩니다.
조금 지우다
비트 AND 연산자( &
)를 사용하여 비트를 지웁니다.
number &= ~(1UL << n);
그러면 number
n
번째 비트가 지워집니다. ~
)를 사용하여 비트 문자열을 반전한 다음 AND를 수행해야 합니다.
약간 토글
XOR 연산자( ^
)를 사용하여 비트를 토글할 수 있습니다.
number ^= 1UL << n;
number
n
번째 비트가 토글됩니다.
조금 확인
당신은 이것을 요구하지 않았지만, 나는 그것을 추가할 수도 있습니다.
비트를 확인하려면 숫자 n을 오른쪽으로 이동한 다음 비트 단위로 AND를 수행합니다.
bit = (number >> n) & 1U;
number
n
번째 비트 값을 bit
넣습니다.
n 번째 비트를 x로 변경
n
번째 비트를 1
또는 0
설정하는 것은 2의 보수 C++ 구현에서 다음을 사용하여 달성할 수 있습니다.
number ^= (-x ^ number) & (1UL << n);
x
가 1
이면 비트 n
이 설정 x
가 0
지워집니다. x
에 다른 값이 있으면 쓰레기가 됩니다. x = !!x
는 0 또는 1로 부울화합니다.
이것을 2의 보수 부정 동작과 독립적으로 만들려면( -1
에 모든 비트가 설정됨) 부호 없는 부정을 사용합니다.
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
설정합니다.
일반적으로 코드를 복사/붙여넣기하지 않는 것이 좋습니다. 그래서 많은 사람들이 전처리기 매크로( 커뮤니티 위키 답변 과 같은)나 일종의 캡슐화를 사용합니다.
Paige Ruten
표준 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 버전은 표준 라이브러리 컴파일 시간 크기의 비트 집합과 비교하여 런타임 크기의 비트 집합을 허용합니다.
Martin York
다른 옵션은 비트 필드를 사용하는 것입니다.
struct bits { unsigned int a:1; unsigned int b:1; unsigned int c:1; }; struct bits mybits;
3비트 필드를 정의합니다(실제로는 3개의 1비트 필드). 비트 연산은 이제 조금(하하) 더 간단해졌습니다:
비트를 설정하거나 지우려면:
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
이것은 고정 크기 비트 필드에서만 작동합니다. 그렇지 않으면 이전 게시물에서 설명한 비트 돌리기 기술에 의존해야 합니다.
Ferruccio
헤더 파일에 정의된 매크로를 사용하여 비트 세트 및 지우기를 처리합니다.
/* 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 #define BITMASK_SET(x, mask) ((x) |= (mask)) #define BITMASK_CLEAR(x, mask) ((x) &= (~(mask))) #define BITMASK_FLIP(x, mask) ((x) ^= (mask)) #define BITMASK_CHECK_ALL(x, mask) (!(~(x) & (mask))) #define BITMASK_CHECK_ANY(x, mask) ((x) & (mask))
Community Wiki
때때로 비트의 이름 을 enum
을 사용할 가치가 있습니다.
enum ThingFlags = { ThingMask = 0x0000, ThingFlag0 = 1 << 0, ThingFlag1 = 1 << 1, ThingError = 1 << 8, }
그런 다음 나중에 이름을 사용합니다. 즉 쓰기
thingstate |= ThingFlag1; thingstate &= ~ThingFlag0; if (thing & ThingError) {...}
설정하고 지우고 테스트합니다. 이렇게 하면 나머지 코드에서 매직 넘버를 숨길 수 있습니다.
그 외에는 Jeremy의 솔루션을 지지합니다.
dmckee --- ex-moderator kitten
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의 필드를 생성합니다. 유일한 까다로운 부분은 1 필드에 단일 0 비트를 설정해야 하는 BitClr() 매크로입니다. 이것은 물결표(~) 연산자로 표시된 것과 동일한 표현식의 1의 보수를 사용하여 수행됩니다.
마스크가 생성되면 비트 및 (&) 또는 (|) 및 xor(^) 연산자를 사용하여 제안한 대로 인수에 적용됩니다. 마스크는 long 유형이므로 매크로는 char, short, int 또는 long에서도 잘 작동합니다.
결론은 이것이 전체 문제 클래스에 대한 일반적인 솔루션이라는 것입니다. 물론 필요할 때마다 명시적인 마스크 값을 사용하여 이러한 매크로 중 하나와 동등한 것을 다시 작성하는 것이 가능하고 적절합니다. 하지만 왜 그렇게 할까요? 매크로 대체는 전처리기에서 발생하므로 생성된 코드는 값이 컴파일러에 의해 상수로 간주된다는 사실을 반영합니다. 비트 조작을 합니다.
확신이 서지 않습니까? 다음은 몇 가지 테스트 코드입니다. 전체 최적화와 _cdecl을 사용하지 않고 Watcom C를 사용하여 결과 디스어셈블리가 가능한 한 깨끗해졌습니다.
----[ 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
----[ 마침 ]------------------------------------------- ----------------------
yogeesh
초보자를 위해 예를 들어 조금 더 설명하고 싶습니다.
예시:
value is 0x55; bitnum : 3rd.
&
연산자는 비트를 확인하는 데 사용됩니다.
0101 0101 & 0000 1000 ___________ 0000 0000 (mean 0: False). It will work fine if the third bit is 1 (then the answer will be True)
토글 또는 뒤집기:
0101 0101 ^ 0000 1000 ___________ 0101 1101 (Flip the third bit without affecting other bits)
|
연산자: 비트 설정
0101 0101 | 0000 1000 ___________ 0101 1101 (set the third bit without affecting other bits)
kapilddit
"임베디드"라는 태그가 붙어 있으므로 마이크로컨트롤러를 사용하고 있다고 가정하겠습니다. 위의 모든 제안은 유효하고 작동합니다(읽기-수정-쓰기, 공용체, 구조체 등).
그러나 오실로스코프 기반 디버깅을 하는 동안 마이크로의 PORTnSET/PORTnCLEAR 레지스터에 값을 직접 쓰는 것과 비교하여 이러한 방법이 CPU 사이클에서 상당한 오버헤드가 있다는 사실에 놀랐습니다. -주파수 ISR의 토글 핀.
익숙하지 않은 사람들을 위해: 제 예에서 마이크로에는 출력 핀을 반영하는 일반 핀 상태 레지스터 PORTn이 있으므로 PORTn |= BIT_TO_SET을 수행하면 해당 레지스터에 대한 읽기-수정-쓰기가 발생합니다. 그러나 PORTnSET / PORTnCLEAR 레지스터는 "이 비트를 1로 만드십시오"(SET) 또는 "이 비트를 0으로 만드십시오"(CLEAR)를 의미하기 위해 '1'을 취하고 "핀을 그대로 두십시오"를 의미하기 위해 '0'을 취합니다. 따라서 비트를 설정하거나 지우는지(항상 편리한 것은 아님)에 따라 두 개의 포트 주소를 갖게 되지만 훨씬 더 빠른 반응과 더 작은 조립 코드를 갖게 됩니다.
John U
unsigned char
에서 size_t
(작업에 효율적이어야 하는 가장 큰 유형)까지 모든 유형의 부호 없는 정수 배열에서 작동하는 제가 가장 좋아하는 비트 산술 매크로입니다.
#define BITOP(a,b,op) \ ((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
비트를 설정하려면:
BITOP(array, bit, |=);
조금 지우려면:
BITOP(array, bit, &=~);
비트를 전환하려면:
BITOP(array, bit, ^=);
약간의 테스트:
if (BITOP(array, bit, &)) ...
등.
R.. GitHub STOP HELPING ICE
비트필드 접근 방식은 임베디드 분야에서 다른 장점이 있습니다. 특정 하드웨어 레지스터의 비트에 직접 매핑되는 구조체를 정의할 수 있습니다.
struct HwRegister { unsigned int errorFlag:1; // one-bit flag field unsigned int Mode:3; // three-bit mode field unsigned int StatusCode:4; // four-bit status code }; struct HwRegister CR3342_AReg;
비트 패킹 순서를 알아야 합니다. MSB가 먼저라고 생각하지만 구현에 따라 다를 수 있습니다. 또한 컴파일러가 바이트 경계를 넘는 필드를 처리하는 방법을 확인하십시오.
그런 다음 이전과 같이 개별 값을 읽고, 쓰고, 테스트할 수 있습니다.
Roddy
임의 유형의 변수에서 임의의 위치에서 비트를 확인합니다.
#define bit_test(x, y) ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )
샘플 사용법:
int main(void) { unsigned char arr[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; for (int ix = 0; ix < 64; ++ix) printf("bit %d is %d\n", ix, bit_test(arr, ix)); return 0; }
참고: 이것은 빠르고(유연성을 감안할 때) 분기되지 않도록 설계되었습니다. Sun Studio 8을 컴파일하면 효율적인 SPARC 기계 코드가 생성됩니다. 또한 amd64에서 MSVC++ 2008을 사용하여 테스트했습니다. 비트를 설정하고 지우기 위해 유사한 매크로를 만드는 것이 가능합니다. 다른 많은 솔루션과 비교하여 이 솔루션의 주요 차이점은 거의 모든 유형의 변수에서 모든 위치에서 작동한다는 것입니다.
John Zwinck
더 일반적으로 임의 크기의 비트맵의 경우:
#define BITS 8 #define BIT_SET( p, n) (p[(n)/BITS] |= (0x80>>((n)%BITS))) #define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS))) #define BIT_ISSET(p, n) (p[(n)/BITS] & (0x80>>((n)%BITS)))
bill
이 프로그램은 데이터 비트를 0에서 1로 또는 1에서 0으로 변경하는 것입니다.
{ unsigned int data = 0x000000F0; int bitpos = 4; int bitvalue = 1; unsigned int bit = data; bit = (bit>>bitpos)&0x00000001; int invbitvalue = 0x00000001&(~bitvalue); printf("%x\n",bit); if (bitvalue == 0) { if (bit == 0) printf("%x\n", data); else { data = (data^(invbitvalue<<bitpos)); printf("%x\n", data); } } else { if (bit == 1) printf("elseif %x\n", data); else { data = (data|(bitvalue<<bitpos)); printf("else %x\n", data); } } }
Gokul Naathan
이것을 사용하십시오:
int ToggleNthBit ( unsigned char n, int num ) { if(num & (1 << n)) num &= ~(1 << n); else num |= (1 << n); return num; }
thangavel
약간의 만지작거림을 많이 하는 경우 마스크를 사용하여 전체 작업을 더 빠르게 수행할 수 있습니다. 다음 함수는 매우 빠르며 여전히 유연합니다(모든 크기의 비트 맵에서 비트 비틀기를 허용합니다).
const unsigned char TQuickByteMask[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, }; /** Set bit in any sized bit mask. * * @return none * * @param bit - Bit number. * @param bitmap - Pointer to bitmap. */ void TSetBit( short bit, unsigned char *bitmap) { short n, x; x = bit / 8; // Index to byte. n = bit % 8; // Specific bit in byte. bitmap[x] |= TQuickByteMask[n]; // Set bit. } /** Reset bit in any sized mask. * * @return None * * @param bit - Bit number. * @param bitmap - Pointer to bitmap. */ void TResetBit( short bit, unsigned char *bitmap) { short n, x; x = bit / 8; // Index to byte. n = bit % 8; // Specific bit in byte. bitmap[x] &= (~TQuickByteMask[n]); // Reset bit. } /** Toggle bit in any sized bit mask. * * @return none * * @param bit - Bit number. * @param bitmap - Pointer to bitmap. */ void TToggleBit( short bit, unsigned char *bitmap) { short n, x; x = bit / 8; // Index to byte. n = bit % 8; // Specific bit in byte. bitmap[x] ^= TQuickByteMask[n]; // Toggle bit. } /** Checks specified bit. * * @return 1 if bit set else 0. * * @param bit - Bit number. * @param bitmap - Pointer to bitmap. */ short TIsBitSet( short bit, const unsigned char *bitmap) { short n, x; x = bit / 8; // Index to byte. n = bit % 8; // Specific bit in byte. // Test bit (logigal AND). if (bitmap[x] & TQuickByteMask[n]) return 1; return 0; } /** Checks specified bit. * * @return 1 if bit reset else 0. * * @param bit - Bit number. * @param bitmap - Pointer to bitmap. */ short TIsBitReset( short bit, const unsigned char *bitmap) { return TIsBitSet(bit, bitmap) ^ 1; } /** Count number of bits set in a bitmap. * * @return Number of bits set. * * @param bitmap - Pointer to bitmap. * @param size - Bitmap size (in bits). * * @note Not very efficient in terms of execution speed. If you are doing * some computationally intense stuff you may need a more complex * implementation which would be faster (especially for big bitmaps). * See (http://graphics.stanford.edu/~seander/bithacks.html). */ int TCountBits( const unsigned char *bitmap, int size) { int i, count = 0; for (i=0; i<size; i++) if (TIsBitSet(i, bitmap)) count++; return count; }
16비트 정수로 비트 'n'을 설정하려면 다음을 수행합니다.
TSetBit( n, &my_int);
비트 번호가 전달하는 비트 맵 범위 내에 있는지 확인하는 것은 사용자의 몫입니다. 바이트, 워드, dwords, qwords 등이 메모리에서 서로 올바르게 매핑되는 리틀 엔디안 프로세서의 경우 (리틀 엔디안 프로세서가 빅 엔디안 프로세서보다 '더 나은' 주된 이유는 아, 화염 전쟁이 오는 것 같습니다. 에...).
Tim Ring
먼저 몇 가지를 가정해 보겠습니다.
num = 55
비트 연산(set, get, clear, toggle)을 수행하기 위한 정수.
n = 4
0 비트 연산을 수행하기 위한 비트 위치 기반.
조금 얻는 방법?
- num 오른쪽 시프트
num
nth
비트를 얻으려면n
번 이동합니다. 그런 다음 1로&
bit = (num >> n) & 1;
어떻게 작동합니까?
0011 0111 (55 in decimal) >> 4 (right shift 4 times) ----------------- 0000 0011 & 0000 0001 (1 in decimal) ----------------- => 0000 0001 (final result)
조금 설정하는 방법?
- 숫자의 특정 비트를 설정합니다. 왼쪽 이동 한
n
번. 그런 다음 비트 OR|
num
연산.
num |= (1 << n); // Equivalent to; num = (1 << n) | num;
어떻게 작동합니까?
0000 0001 (1 in decimal) << 4 (left shift 4 times) ----------------- 0001 0000 | 0011 0111 (55 in decimal) ----------------- => 0001 0000 (final result)
조금 지우는 방법?
- 왼쪽 시프트 1,
n
번 즉1 << n
. - 위의 결과로 비트 보수를 수행하십시오. 따라서 n번째 비트는 설정되지 않고 나머지 비트는 설정됩니다. 즉
~ (1 << n)
. - 마지막으로 위의 결과와
num
으로 비트 AND&
연산을 수행합니다. 위의 세 단계를 함께 쓰면num & (~ (1 << n))
;
num &= (~(1 << n)); // Equivalent to; num = num & (~(1 << n));
어떻게 작동합니까?
0000 0001 (1 in decimal) << 4 (left shift 4 times) ----------------- ~ 0001 0000 ----------------- 1110 1111 & 0011 0111 (55 in decimal) ----------------- => 0010 0111 (final result)
조금 토글하는 방법?
비트를 토글하려면 비트 XOR ^
연산자를 사용합니다. Bitwise XOR 연산자는 두 피연산자의 해당 비트가 다르면 1로 평가하고, 그렇지 않으면 0으로 평가합니다.
즉, 비트를 토글하려면 토글하려는 비트와 1로 XOR 연산을 수행해야 합니다.
num ^= (1 << n); // Equivalent to; num = num ^ (1 << n);
어떻게 작동합니까?
- 토글할 비트가 0이면
0 ^ 1 => 1
입니다. - 토글할 비트가 1이면
1 ^ 1 => 0
입니다.
0000 0001 (1 in decimal) << 4 (left shift 4 times) ----------------- 0001 0000 ^ 0011 0111 (55 in decimal) ----------------- => 0010 0111 (final result)
권장 자료 - 비트 연산자 연습
Pankaj Prakash
bitset
답변 확장:
#include <iostream> #include <bitset> #include <string> using namespace std; int main() { bitset<8> byte(std::string("10010011"); // Set Bit byte.set(3); // 10010111 // Clear Bit byte.reset(2); // 10010101 // Toggle Bit byte.flip(7); // 00010101 cout << byte << endl; return 0; }
kendotwill
Visual C 2010 및 아마도 다른 많은 컴파일러는 부울 연산을 직접 지원합니다. 비트에는 부울과 마찬가지로 두 가지 가능한 값이 있으므로 대신 부울을 사용할 수 있습니다. 단일 비트보다 더 많은 공간을 차지하더라도 이 표현의 메모리. sizeof()
연산자도 제대로 작동합니다.
bool IsGph[256], IsNotGph[256]; // Initialize boolean array to detect printable characters for(i=0; i<sizeof(IsGph); i++) { IsGph[i] = isgraph((unsigned char)i); }
따라서 귀하의 질문에 IsGph[i] =1
또는 IsGph[i] =0
하면 bool을 쉽게 설정하고 지울 수 있습니다.
인쇄할 수 없는 문자를 찾으려면:
// Initialize boolean array to detect UN-printable characters, // then call function to toggle required bits true, while initializing a 2nd // boolean array as the complement of the 1st. for(i=0; i<sizeof(IsGph); i++) { if(IsGph[i]) { IsNotGph[i] = 0; } else { IsNotGph[i] = 1; } }
이 코드에는 "특별한" 것이 없습니다. 이것은 기술적으로 정수처럼 취급합니다. 2개의 값과 2개의 값만 보유할 수 있는 1비트 정수입니다.
한 번 이 접근 방식을 사용하여 6자리 대출 번호를 비트 배열에 대한 인덱스로 사용하여 대출 번호가 ISAM 키인 중복 대출 레코드를 찾은 적이 있습니다. 엄청나게 빠르고 8개월 후에 우리가 데이터를 가져오는 메인프레임 시스템이 실제로 오작동하고 있음이 입증되었습니다. 비트 배열의 단순성은 예를 들어 검색 접근 방식에 비해 정확성에 대한 확신을 매우 높입니다.
user1899861
Linux 커널에서 C 프로그래밍으로 이 모든 작업을 수행하려면 Linux 커널의 표준 API를 사용하는 것이 좋습니다.
https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html 참조
set_bit Atomically set a bit in memory clear_bit Clears a bit in memory change_bit Toggle a bit in memory test_and_set_bit Set a bit and return its old value test_and_clear_bit Clear a bit and return its old value test_and_change_bit Change a bit and return its old value test_bit Determine whether a bit is set
참고: 여기에서 전체 작업은 단일 단계에서 발생합니다. 따라서 이들 모두는 SMP 컴퓨터에서도 원자성 이 보장되며 프로세서 간에 일관성을 유지하는 데 유용합니다.
Jeegar Patel
int set_nth_bit(int num, int n){ return (num | 1 << n); } int clear_nth_bit(int num, int n){ return (num & ~( 1 << n)); } int toggle_nth_bit(int num, int n){ return num ^ (1 << n); } int check_nth_bit(int num, int n){ return num & (1 << n); }
Sazzad Hissain Khan
다음은 내가 사용하는 몇 가지 매크로입니다.
SET_FLAG(Status, Flag) ((Status) |= (Flag)) CLEAR_FLAG(Status, Flag) ((Status) &= ~(Flag)) INVALID_FLAGS(ulFlags, ulAllowed) ((ulFlags) & ~(ulAllowed)) TEST_FLAGS(t,ulMask, ulBit) (((t)&(ulMask)) == (ulBit)) IS_FLAG_SET(t,ulMask) TEST_FLAGS(t,ulMask,ulMask) IS_FLAG_CLEAR(t,ulMask) TEST_FLAGS(t,ulMask,0)
sam msft
단일 비트를 어떻게 설정, 지우고 토글합니까?
마스크를 형성하려고 할 때 일반적인 코딩 함정을 해결하려면:
1
은 항상 충분히 넓지 않습니다.
어떤 문제는 때 발생하는 number
보다 더 넓은 타입 1
?
x
1 << x
대해 너무 커서 정의되지 않은 동작 (UB)으로 이어질 수 있습니다. x
가 너무 크지 않더라도 ~
는 최상위 비트를 충분히 뒤집지 못할 수 있습니다.
// assume 32 bit int/unsigned unsigned long long number = foo(); unsigned x = 40; number |= (1 << x); // UB number ^= (1 << x); // UB number &= ~(1 << x); // UB x = 10; number &= ~(1 << x); // Wrong mask, not wide enough
1이 충분히 넓은지 확인하려면:
코드는 1ull
또는 현학적 (uintmax_t)1
하고 컴파일러가 최적화하도록 할 수 있습니다.
number |= (1ull << x); number |= ((uintmax_t)1 << x);
또는 캐스트 - 캐스트를 정확하고 최신 상태로 유지하는 코딩/검토/유지 관리 문제를 만듭니다.
number |= (type_of_number)1 << x;
number
유형만큼 넓은 수학 연산을 수행 1
을 승격시키십시오.
number |= (number*0 + 1) << x;
대부분의 비트 조작과 마찬가지로 서명된 유형보다 서명 되지 않은 유형으로 작업하는 것이 가장 좋습니다.
chux - Reinstate Monica
이 프로그램은 @Jeremy의 위 솔루션을 기반으로 합니다. 누군가가 빨리 놀고 싶다면.
public class BitwiseOperations { public static void main(String args[]) { setABit(0, 4); // set the 4th bit, 0000 -> 1000 [8] clearABit(16, 5); // clear the 5th bit, 10000 -> 00000 [0] toggleABit(8, 4); // toggle the 4th bit, 1000 -> 0000 [0] checkABit(8,4); // check the 4th bit 1000 -> true } public static void setABit(int input, int n) { input = input | ( 1 << n-1); System.out.println(input); } public static void clearABit(int input, int n) { input = input & ~(1 << n-1); System.out.println(input); } public static void toggleABit(int input, int n) { input = input ^ (1 << n-1); System.out.println(input); } public static void checkABit(int input, int n) { boolean isSet = ((input >> n-1) & 1) == 1; System.out.println(isSet); } } Output : 8 0 0 true
Balaji Boggaram Ramanarayan
여러 비트 변경을 지원하는 템플릿 버전(헤더 파일에 넣음)(AVR 마이크로컨트롤러 btw에서 작동):
namespace bit { template <typename T1, typename T2> constexpr inline T1 bitmask(T2 bit) {return (T1)1 << bit;} template <typename T1, typename T3, typename ...T2> constexpr inline T1 bitmask(T3 bit, T2 ...bits) {return ((T1)1 << bit) | bitmask<T1>(bits...);} /** Set these bits (others retain their state) */ template <typename T1, typename ...T2> constexpr inline void set (T1 &variable, T2 ...bits) {variable |= bitmask<T1>(bits...);} /** Set only these bits (others will be cleared) */ template <typename T1, typename ...T2> constexpr inline void setOnly (T1 &variable, T2 ...bits) {variable = bitmask<T1>(bits...);} /** Clear these bits (others retain their state) */ template <typename T1, typename ...T2> constexpr inline void clear (T1 &variable, T2 ...bits) {variable &= ~bitmask<T1>(bits...);} /** Flip these bits (others retain their state) */ template <typename T1, typename ...T2> constexpr inline void flip (T1 &variable, T2 ...bits) {variable ^= bitmask<T1>(bits...);} /** Check if any of these bits are set */ template <typename T1, typename ...T2> constexpr inline bool isAnySet(const T1 &variable, T2 ...bits) {return variable & bitmask<T1>(bits...);} /** Check if all these bits are set */ template <typename T1, typename ...T2> constexpr inline bool isSet (const T1 &variable, T2 ...bits) {return ((variable & bitmask<T1>(bits...)) == bitmask<T1>(bits...));} /** Check if all these bits are not set */ template <typename T1, typename ...T2> constexpr inline bool isNotSet (const T1 &variable, T2 ...bits) {return ((variable & bitmask<T1>(bits...)) != bitmask<T1>(bits...));} }
사용 예:
#include <iostream> #include <bitset> // for console output of binary values // and include the code above of course using namespace std; int main() { uint8_t v = 0b1111'1100; bit::set(v, 0); cout << bitset<8>(v) << endl; bit::clear(v, 0,1); cout << bitset<8>(v) << endl; bit::flip(v, 0,1); cout << bitset<8>(v) << endl; bit::clear(v, 0,1,2,3,4,5,6,7); cout << bitset<8>(v) << endl; bit::flip(v, 0,7); cout << bitset<8>(v) << endl; }
BTW: 컴파일러에 최적화 인수(예: -O3)를 보내지 않으면 constexpr 및 인라인이 사용되지 않는 것으로 나타났습니다. https://godbolt.org/ 에서 코드를 자유롭게 시도하고 ASM 출력을 보십시오.
Joakim L. Christiansen
-1을 사용하지 않고 n번째 비트를 x(비트 값)로 설정
때때로 -1 등이 어떤 결과를 가져올지 확실하지 않은 경우 -1을 사용하지 않고 n번째 비트를 설정하고 싶을 수 있습니다.
number = (((number | (1 << n)) ^ (1 << n))) | (x << n);
설명: ((number | (1 << n)
은 n번째 비트를 1로 설정하고(여기서 |
비트 OR을 나타냄), (...) ^ (1 << n)
을 사용하여 n번째 비트를 0으로 설정하고 마지막으로 (...) | x << n)
으로 0인 n번째 비트를 (비트 값) x
합니다.
golang
에서도 작동합니다.
Dominic van der Zypen
다음은 기본 비트 연산을 수행하는 C의 루틴입니다.
#define INT_BIT (unsigned int) (sizeof(unsigned int) * 8U) //number of bits in unsigned int int main(void) { unsigned int k = 5; //k is the bit position; here it is the 5th bit from the LSb (0th bit) unsigned int regA = 0x00007C7C; //we perform bitwise operations on regA regA |= (1U << k); //Set kth bit regA &= ~(1U << k); //Clear kth bit regA ^= (1U << k); //Toggle kth bit regA = (regA << k) | regA >> (INT_BIT - k); //Rotate left by k bits regA = (regA >> k) | regA << (INT_BIT - k); //Rotate right by k bits return 0; }
lckid2004
n 비트를 변경하려면 C 언어에서 다음 기능 중 하나를 시도하십시오.
char bitfield; // Start at 0th position void chang_n_bit(int n, int value) { bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) )); }
또는
void chang_n_bit(int n, int value) { bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n))); }
또는
void chang_n_bit(int n, int value) { if(value) bitfield |= 1 << n; else bitfield &= ~0 ^ (1 << n); } char get_n_bit(int n) { return (bitfield & (1 << n)) ? 1 : 0; }
Vincet
출처 : http:www.stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit
'etc. > StackOverFlow' 카테고리의 다른 글
jQuery로 입력을 비활성화/활성화하시겠습니까? (0) | 2021.11.13 |
---|---|
설치된 npm 패키지의 버전 찾기 (0) | 2021.11.13 |
JavaScript에서 쿼리 문자열 값을 얻으려면 어떻게 해야 합니까? (0) | 2021.11.11 |
요소 외부의 클릭을 어떻게 감지합니까? (0) | 2021.11.11 |
JavaScript를 사용하여 JSON 예쁘게 인쇄하기 (0) | 2021.11.11 |