source

싱글 비트를 설정, 클리어 및 토글하려면 어떻게 해야 합니까?

nicesource 2023. 2. 6. 23:46
반응형

싱글 비트를 설정, 클리어 및 토글하려면 어떻게 해야 합니까?

설정, 클리어 및 전환 방법은 무엇입니까?

비트 설정

연산자OR')를 합니다.|을 클릭합니다.

number |= 1UL << n;

★★★★★★n of of의 numbern합니다.1 등 비트까지 »n-1를 는,n bittwh.dwh.dwh.dwh

1ULLnumberunsigned long의 프로모션1UL << n 후가 아니면 않는다1UL << n정의되지 않은 동작으로 인해 폭보다 더 많이 이동한다.long하다

약간의 클리어

연산자AND')를 사용합니다.& 합니다을 클릭합니다.

number &= ~(1UL << n);

이것으로, 가 클리어 됩니다.n of of의 number 단위 연산자NOT 연산자)로~ ), 하다, 하다, 하다, 하다

조금 전환하다

연산자XOR ')^하여 비트를 할 수 를 사용하여 비트를 전환할 수 있습니다.

number ^= 1UL << n;

★★★★★★n of of의 number.

조금 체크하고 있다

네가 이걸 달라고 한 건 아니지만, 내가 추가하는 게 낫겠어.

비트를 확인하려면 숫자 n을 오른쪽으로 이동한 다음 비트 AND를 선택합니다.

bit = (number >> n) & 1U;

그 때문에, 의 가치가 높아집니다.n of of의 number 「」로bit.

n번째 비트를 x로 변경

의 설정n를 """ 중 하나로 합니다.1 ★★★★★★★★★★★★★★★★★」0 2 의C++에서는, 다음과 할 수 .: 、 2 + C++ 、 음 、 음음음 。

number ^= (-x ^ number) & (1UL << n);

★★nx1를 클리어했습니다.x0.x이치노 x = !!x는 0 10의 1로 됩니다.

2의 (여기서 「2」는 「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)) will the will will 。n 및 "th"(x << n) 설정을 .n 게 th th th th th 。x.

또한 일반적으로 코드를 복사/붙이지 않는 것이 좋습니다.따라서 많은 사람들이 프리프로세서 매크로(커뮤니티 Wiki의 답변 등) 또는 일종의 캡슐화를 사용합니다.

표준 C++ 라이브러리 사용:

또는 Boost 버전:

직접 롤할 필요가 없습니다.

#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

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

때때로 사용할 가치가 있습니다.enum비트 이름 지정:

enum ThingFlags = {
  ThingMask  = 0x0000,
  ThingFlag0 = 1 << 0,
  ThingFlag1 = 1 << 1,
  ThingError = 1 << 8,
}

그럼 나중에 이름을 사용하세요.즉, 쓰기

thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}

설정, 클리어, 테스트.이렇게 하면 암호의 나머지 부분에서 마법 번호를 숨길 수 있습니다.

외에는 페이지 루텐의 해결책을 지지합니다.

snap-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비트를 설정할 필요가 있습니다.이것은 tilde(~) 연산자가 나타내는 것과 같은 식의 1의 보수를 사용하여 실현됩니다.

마스크가 생성되면 비트 및 (&) 또는 (|) 및 xor (^) 연산자를 사용하여 사용자가 제안하는 대로 인수에 적용됩니다.마스크는 긴 타입이므로 매크로는 chars, shorts, int 또는 longs에서도 동일하게 동작합니다.

결론은 이것이 모든 종류의 문제에 대한 일반적인 해결책이라는 것입니다.물론 이러한 매크로에 상당하는 것을 필요에 따라서 명시적인 마스크 값으로 고쳐 쓰는 것도 가능합니다만, 그 이유는 무엇입니까?매크로 치환은 프리프로세서에서 이루어지기 때문에 생성된 코드는 값이 컴파일러에 의해 일정하다고 간주된다는 사실을 반영합니다.즉, 비트 조작이 필요할 때마다 범용 매크로를 사용하는 것이 효율적입니다.

납득이 안 가?다음은 테스트 코드입니다.완전 최적화 상태에서 _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;
}

----[테스트]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

---------------------------------------------------------------------------------

초심자를 위해 예를 들어 조금 더 설명하겠습니다.

예를 들어:

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)

이 태그는 내장되어 있기 때문에 마이크로컨트롤러를 사용하고 있다고 생각합니다.상기 제안은 모두 유효하고 유효합니다(읽기, 변경, 쓰기, 조합, 구조 등).

그러나 오실로스코프 기반 디버깅을 하는 동안 이러한 메서드는 마이크로의 PORTnSET/PORTnCLEAR 레지스터에 직접 값을 쓰는 것에 비해 CPU 사이클에서 상당한 오버헤드가 발생한다는 것을 알게 되어 매우 놀랐습니다. 이 레지스터는 엄격한 루프/고주파 ISR의 토글링 핀이 있는 곳에서 실질적인 차이를 보입니다.

익숙하지 않은 사용자:이 예에서 마이크로에는 출력 핀을 반영하는 일반적인 핀 상태 레지스터 PORTn이 있으므로 PORTn |= BIT_를 수행합니다.TO_SET에 의해 해당 레지스터에 읽기-수정-기입이 이루어집니다.단, PORTnSET/PORTnCLEAR 레지스터는 "Please make this bit 1"(SET) 또는 "Please make this bit 0"(CLEAR)을 의미하며 "0"(CLEAR)을 의미하기 때문에 비트를 설정할지 클리어할지에 따라 2개의 포트 주소가 할당되지만(항상 편리하지는 않음)의 응답은 훨씬 빨라지고 어셈블리 코드는 작아집니다.

비트 매크로가 이 매크로는 의 부호 할 수 있습니다.이것은 모든 유형의 부호 없는 정수 배열에서 동작합니다.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, &)) ...

기타.

몇 일을 .
num = 55설정, 설정하다, 클리어, 토글하다
n = 4비트 동작을 수행하기 위한 0 베이스 비트 위치.

어떻게 구하지?

  1. 「 」를 nth shift bit bit bit 。num,n정해서 AND를 AND로 . AND로 하다&로 하다
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)

비트는 어떻게 해?

  1. 시프트 1 왼쪽 시프트 1n OR을 해 주세요. 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. 1, 왼쪽 시프트 1,n몇몇??1 << n.
  2. 위의 결과를 사용하여 비트 보정을 수행합니다.그러면 n번째 비트가 설정 해제되고 나머지 비트가 설정됩니다. ~ (1 << n).
  3. AND를 AND로 .&와 「」의 을 실시.num의 세 , '아까보다'라고 쓸수.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를 사용합니다.^비트 단위 경우 경우 0으로됩니다. XOR은 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)

권장 판독치 - 비트 연산자 연습

비트필드 방식에는 임베디드 분야에서도 다른 장점이 있습니다.특정 하드웨어 레지스터의 비트에 직접 매핑하는 구조를 정의할 수 있습니다.

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가 우선이지만 구현에 따라 다를 수 있습니다.또한 컴파일러 핸들러가 바이트 경계를 넘나드는 방법도 확인합니다.

그런 다음 이전과 같이 개별 값을 읽고, 쓰고, 테스트할 수 있습니다.

임의 유형의 변수에서 임의 위치에서 비트를 확인합니다.

#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을 사용하여 테스트한 적도 있습니다.비트를 설정 및 클리어하기 위해 유사한 매크로를 만들 수 있습니다.이 솔루션이 다른 솔루션과 비교했을 때 가장 큰 차이점은 거의 모든 유형의 변수에서 모든 위치에서 작동한다는 것입니다.

보다 일반적인, 임의의 크기의 비트맵의 경우:

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

이 프로그램은 데이터 비트를 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);
        }
    }
}

만약 당신이 많은 빈둥거림을 하고 있다면, 당신은 모든 것을 더 빨리 할 수 있는 마스크를 사용하는 것이 좋을지도 모른다.다음 함수는 매우 빠르고 유연합니다(모든 크기의 비트 맵에서 비트를 트위들링할 수 있습니다).

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

비트 번호가 패스하는 비트 맵의 범위 내에 있는지 확인하는 것은 사용자의 책임입니다.바이트, 워드, dword, qwords 등이 메모리 내에서 서로 올바르게 매핑되는 작은 엔디안 프로세서의 경우(작은 엔디안 프로세서가 빅 엔디안 프로세서보다 '더 나은' 주된 이유, 아, 불꽃 전쟁이 시작되는 것 같은 느낌이 듭니다).

사용방법:

int ToggleNthBit ( unsigned char n, int num )
{
    if(num & (1 << n))
        num &= ~(1 << n);
    else
        num |= (1 << n);

    return num;
}

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

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 컴퓨터에서도 원자성이 보증되며 프로세서 간에 일관성을 유지하는 데 유용합니다.

Visual C 2010 및 기타 많은 컴파일러는 부울 연산을 직접 지원합니다.비트는 부울값과 마찬가지로 2개의 가능한 값을 가지고 있기 때문에 부울란을 대신 사용할 수 있습니다(이 표현에서는 메모리 내의 1비트보다 더 많은 공간을 차지하더라도).이 동작은,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설정 및 클리어 작업을 쉽게 합니다.

인쇄할 수 없는 문자를 찾으려면:

//  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자리 대출 번호를 인덱스로 사용하여 중복 대출 기록을 검색한 적이 있습니다.여기서 loan_number는 ISAM 키입니다.8개월 후에 데이터를 가져오는 메인프레임 시스템이 실제로 오작동하고 있음을 증명했습니다.비트 어레이는 단순하기 때문에 검색 접근 방식보다 정확성에 대한 확신이 매우 높아집니다.

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

사용하는 매크로는 다음과 같습니다.

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)

단일 비트를 설정, 삭제 및 전환하려면 어떻게 해야 합니까?

마스크 형성을 시도할 때 공통 코딩 함정에 대처하려면:
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;

.1「연산」의 연산자를 합니다.number.

number |= (number*0 + 1) << x;

대부분의 비트 조작과 마찬가지로 서명된 유형이 아닌 서명되지 않은 유형으로 작업하는 것이 좋습니다.

이 프로그램은 @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

여러 비트 변경(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: 컴파일러에 optimizer 인수(예: -O3)를 전송하지 않으면 constexpr과 inline은 사용되지 않습니다.https://godbolt.org/ 에서 코드를 사용해 보고, ASM 의 출력을 봐 주세요.

기본 비트 연산을 실행하는 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;   
}

-1을 사용하지 않고 n번째 비트를 x(비트 값)로 설정

경우에 따라서는 -1 등의 결과가 어떻게 될지 확실하지 않은 경우 -1을 사용하지 않고 n번째 비트를 설정할 수 있습니다.

number = (((number | (1 << n)) ^ (1 << n))) | (x << n);

명::((number | (1 << n)1로 서 n번째 비트는 1입니다).| OR를 나타냅니다.(...) ^ (1 << n)0으로 으로 n번째 비트를 0으로 설정합니다.(...) | x << n)0으로 하고 ( 0으로 설정합니다.x.

은 또한 이, this, 니, this, this, 효, 효, 효, 효, this, this, this, this,golang.

다음 중 하나의 함수를 C 언어로 사용하여n비트를 변경합니다.

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

언급URL : https://stackoverflow.com/questions/47981/how-do-i-set-clear-and-toggle-a-single-bit

반응형