단일 비트를 어떻게 설정하고 지우고 토글합니까?


2567

비트를 어떻게 설정하고 지우고 토글합니까?


64
이것을 읽으십시오 : graphics.stanford.edu/~seander/bithacks.html 그리고 이것을 마스터 할 때 이것을 읽으십시오 : realtimecollisiondetection.net/blog/?p=78
ugasoft

9
또한 체크 아웃에 관심이있을 수 있습니다 비트 Twiddler , 비트 만지작 해킹집계 매직 알고리즘 .

답변:


3597

비트 설정

비트 OR 연산자 ( |)를 사용하여 비트 를 설정하십시오.

number |= 1UL << n;

n비트 가 설정됩니다 number. st 비트 n를 설정하려면 1up 을 0 n-1으로 설정하고 nth 비트 를 설정하려면

보다 넓은 1ULL경우 사용 ; 의 너비 이상으로 이동하는 정의되지 않은 동작이 어디인지 평가 한 후에야 프로모션이 진행 됩니다. 나머지 모든 예제에도 동일하게 적용됩니다.numberunsigned long1UL << n1UL << nlong

조금 지우기

비트 AND 연산자 ( &)를 사용하여 비트 를 지 웁니다.

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

그것의 nth 비트를 취소합니다 number. 비트 NOT 연산자 ( ~)를 사용하여 비트 문자열을 반전 한 다음 AND해야합니다.

조금 토글

XOR 연산자 ( ^)를 사용하여 비트를 토글 할 수 있습니다.

number ^= 1UL << n;

nth 비트를 토글합니다 number.

조금 확인

당신은 이것을 요구하지 않았지만 나는 그것을 추가 할 수도 있습니다.

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

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

그것은 nth 비트의 값을 number변수 에 넣을 것입니다 bit.

n 번째 비트를 x로 변경

2의 보수 C ++ 구현에서 다음과 같이 nth 비트를 설정 1하거나 0달성 할 수 있습니다.

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

비트는 n경우 설정 될 것 x입니다 1, 그리고 경우 삭제 x입니다 0. x다른 가치가 있다면 쓰레기가 생깁니다. x = !!x0 또는 1로 부울합니다.

이것을 2의 보수 부정 행위 ( -11의 보수 또는 부호 / 크기 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의 답변 아래로 ) 또는 캡슐화를 사용합니다.


128
비트 세트 / 클리어 (예 : AVR 마이크로 컨트롤러)를 기본적으로 지원하는 플랫폼에서 컴파일러는 x가 항상 'myByte | = (1 << x)'를 네이티브 비트 세트 / 클리어 명령어로 변환한다는 점에 유의하고 싶습니다. 상수, 예 : (1 << 5) 또는 const 부호없는 x = 5
Aaron Aaron

52
비트 = 수 & (1 << x); 비트 유형이 _Bool (<stdbool.h>)이 아니면 비트 x 값을 비트에 넣지 않습니다. 그렇지 않으면 비트 = !! (숫자 & (1 << x));
Chris Young

23
마지막으로 bit = (number >> x) & 1
바꾸지 않으시겠습니까

42
1int서명 된 리터럴입니다. 따라서 여기의 모든 작업은 표준에 의해 잘 정의되지 않은 부호있는 숫자로 작동합니다. 표준은 2의 보수 또는 산술 시프트를 보장하지 않으므로 사용하는 것이 좋습니다 1U.
Siyuan Ren

50
number = number & ~(1 << n) | (x << n);n 번째 비트를 x로 변경하는 것을 선호 합니다.
jiasli

459

표준 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 버전은 표준 라이브러리 컴파일 타임 크기 비트 세트와 비교하여 런타임 크기 비트 세트를 허용합니다 .


34
+1. std :: bitset을 "C"에서 사용할 수는 없지만 저자가 "C ++", AFAIK로 질문에 태그를 달았을 때 답이 가장 좋습니다 ... std :: vector <bool>는 다른 방법입니다. 하나의 장점과 단점을 알고있는 경우
paercebal

23
@andrewdotnich : vector <bool>은 불행히도 값을 비트로 저장하는 특수화입니다. 자세한 내용은 gotw.ca/publications/mill09.htm 을 참조하십시오 .
Niklas

71
이 태그가 포함되어 있기 때문에 아무도 언급하지 않았을 수 있습니다. 대부분의 임베디드 시스템에서는 전염병과 같은 STL을 피할 수 있습니다. 또한 부스트 지원은 대부분의 임베디드 컴파일러에서 발견하기 매우 드문 조류입니다.
Lundin

17
@Martin 매우 사실입니다. STL 및 템플릿과 같은 특정 성능 킬러 외에도 많은 임베디드 시스템은 전체 표준 라이브러리를 완전히 피할 수 있습니다. 임베디드 브랜치의 대부분은 정적 코드 분석 툴을 필요로하는 MISRA와 같은 표준을 수용하고 있습니다 (모든 소프트웨어 전문가는 임베디드 툴뿐만 아니라 이러한 툴을 사용해야합니다). 일반적으로 특정 컴파일러에서 소스 코드를 사용할 수있는 경우 전체 표준 라이브러리를 통해 정적 분석을 실행하는 것보다 사람들이 수행하는 것이 더 좋습니다.
룬딘

37
@Lundin : 당신의 진술은 지나치게 광범위합니다 (따라서 논쟁하기에는 쓸모가 없습니다). 나는 그것이 사실이라면 상황을 찾을 수 있다고 확신합니다. 이것은 나의 초기 포인트를 변경하지 않습니다. 이 두 클래스는 임베디드 시스템에서 사용하기에 완벽하게 적합합니다 (그리고 나는 그것들이 사용된다는 사실을 알고 있습니다). STL / 부스트가 임베디드 시스템에서 사용되지 않는다는 초기 시점도 잘못되었습니다. 나는 그것을 사용하지 않는 시스템과 그것들을 사용하는 시스템조차도 신중하게 사용되지만 확실히 사용되지 않는다고 말하는 것은 정확하지 않습니다 (시스템이 사용 되었기 때문에).
Martin York

248

다른 옵션은 비트 필드를 사용하는 것입니다.

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

이것은 고정 크기 비트 필드에서만 작동합니다. 그렇지 않으면 이전 게시물에서 설명한 비트 트위들 링 기술에 의존해야합니다.


68
나는 항상 비트 필드를 사용하는 것이 나쁜 생각이라는 것을 알았습니다. 비트가 할당되는 순서 (위 또는 아래에서)를 제어 할 수 없으므로 한 번에 비트를 제외하고 안정적이고 이식 가능한 방식으로 값을 직렬화 할 수 없습니다. DIY 비트 산술을 비트 필드와 혼합하는 것도 불가능합니다 (예 : 한 번에 여러 비트를 테스트하는 마스크 만들기). 물론 &&를 사용할 수 있고 컴파일러가이를 올바르게 최적화하기를 희망합니다 ...
R .. GitHub ICE HELPING ICE

34
비트 필드는 여러 가지면에서 좋지 않습니다. 거의 그것에 관한 책을 쓸 수 있습니다. 실제로 MISRA-C 준수가 필요한 비트 필드 프로그램을 위해 거의 그렇게해야했습니다. MISRA-C는 모든 구현 정의 동작을 문서화하도록 강요하여 비트 필드에서 잘못 될 수있는 모든 것에 대한 에세이를 작성했습니다. 비트 순서, 엔디안, 패딩 비트, 패딩 바이트, 다양한 기타 정렬 문제, 비트 필드와의 암시 적 및 명시 적 유형 변환, int를 사용하지 않는 경우 UB 등 대신, 버그를 줄이고 휴대용 코드를 작성하려면 비트 연산자를 사용하십시오. 비트 필드는 완전히 중복됩니다.
Lundin

44
대부분의 언어 기능과 마찬가지로 비트 필드는 올바르게 사용되거나 남용 될 수 있습니다. 여러 개의 작은 값을 하나의 int로 묶어야하는 경우 비트 필드가 매우 유용 할 수 있습니다. 반면에 비트 필드가 실제 포함하는 int에 매핑되는 방식에 대한 가정을 시작하면 문제가 있습니다.
Ferruccio

4
@endolith : 좋은 생각이 아닙니다. 작동시킬 수는 있지만 다른 프로세서, 다른 컴파일러 또는 동일한 컴파일러의 다음 릴리스로 이식 할 수있는 것은 아닙니다.
Ferruccio

3
@Yasky와 Ferruccio는이 접근법에 대해 sizeof ()에 대해 다른 답변을 얻는 것은 컴파일러뿐만 아니라 하드웨어 간의 호환성 문제를 설명해야합니다. 우리는 때때로 언어 나 정의 된 런타임으로 이러한 문제를 해결했다고 스스로를 속이는 것이지만 실제로는 '내 기계에서 작동합니까?'로 귀착됩니다. 당신은 내포 된 사람들이 내 존중과 동정심을 가지고 있습니다.
Kelly S. French

181

비트 파일을 처리하고 지우기 위해 헤더 파일에 정의 된 매크로를 사용합니다.

/* 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))

17
어, 나는 이것이 5 살짜리 게시물이라는 것을 알고 있지만 그 매크로들 중에서는 논란의 여지가 없습니다. Dan
Robert Kelly

11
BITMASK_CHECK(x,y) ((x) & (y))((x) & (y)) == (y)그렇지 않으면 멀티 비트 마스크에서 잘못된 결과를 반환 해야합니다 (예 : 5vs. 3) / * Hello 모든 묘비에게 :) * /
brigadir

7
1(uintmax_t)1누군가이 매크로를 long더 큰 유형 에서 사용하려고 할 경우에 유사하거나 유사 해야합니다.
MM

2
BITMASK_CHECK_ALL(x,y)다음과 같이 구현 될 수 있음!~((~(y))|(x))
Handy999

3
@ Handy999 De Morgan의 법칙을 적용하고 다시 정리 한 후에 왜 이것이 작동하는지 알기가 조금 더 쉽습니다.!(~(x) & (y))
Tavian Barnes

114

때때로 비트 이름enum지정 하기 위해를 사용하는 것이 좋습니다 :

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

그런 다음 나중에 이름을 사용하십시오 . 즉 쓰기

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

설정하고 지우고 테스트합니다. 이 방법으로 나머지 코드에서 마법의 숫자를 숨길 수 있습니다.

그 외에는 Jeremy의 솔루션을 보증합니다.


1
또는 clearbits()대신에 기능을 만들 수 &= ~있습니다. 왜 이것을 위해 열거 형을 사용하고 있습니까? 나는 그것들이 숨겨진 임의의 값으로 고유 한 변수를 생성하기위한 것이라고 생각했지만 각각에 명확한 값을 할당하고 있습니다. 그렇다면 변수로 정의하는 것의 장점은 무엇입니까?
endolith

4
@endolith : enum관련된 상수 세트 에 s를 사용하면 c 프로그래밍에서 먼 길을 갔다. 현대 컴파일러의 유일한 장점 const short은 명시 적으로 그룹화되어 있다는 것 이상의 이점 이 있다고 생각합니다. 그리고 비트 마스크 이외의 다른 것을 원할 때 자동 번호 매기기를 얻습니다. 물론 C ++에서는 고유 한 유형을 형성하여 정적 오류 검사를 약간 추가합니다.
dmckee --- 전 운영자 고양이

비트의 가능한 각 값에 대해 상수를 정의하지 않으면 정의되지 않은 열거 형 상수가 표시됩니다. 예를 들어 의 enum ThingFlags값은 무엇입니까 ThingError|ThingFlag1?
루이스 콜로라도

6
이 방법을 사용하는 경우 열거 형 상수는 항상 부호있는 유형이라는 것을 명심하십시오 int. 암시 적 정수 승격 또는 부호있는 유형에 대한 비트 단위 연산으로 인해 모든 방식의 미묘한 버그가 발생할 수 있습니다. thingstate = ThingFlag1 >> 1예를 들어 구현 정의 동작을 호출합니다. thingstate = (ThingFlag1 >> x) << y정의되지 않은 동작을 호출 할 수 있습니다. 등등. 안전을 위해 항상 부호없는 유형으로 캐스트하십시오.
Lundin

1
@Lundin : C ++ 11부터 다음과 같은 열거 형의 기본 유형을 설정할 수 있습니다. enum My16Bits: unsigned short { ... };
Aiken Drum

47

에서 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] ------------------------------------------- ----------------------


3
이것에 대해 2 가지 : (1) 매크로를 꼼꼼히 살펴보면, 일부는 매크로가 실제로 arg에서 비트를 설정 / 클리어 / 플립 비트한다고 잘못 믿지만 할당이 없습니다. (2) test.c가 완료되지 않았습니다. 더 많은 사례를 실행하면 문제를 발견 할 것으로 생각됩니다 (독서 연습)
Dan

19
-1 이것은 단지 이상한 난독 화입니다. 매크로 뒤에 언어 구문을 숨겨서 C 언어를 다시 발명하지 마십시오 . 이는 매우 나쁜 습관입니다. 그런 다음 몇 가지 이상한 점이 있습니다. 먼저 1L이 서명됩니다. 즉, 모든 비트 연산이 서명 된 유형으로 수행됩니다. 이 매크로에 전달 된 모든 것은 부호있는 긴 것으로 리턴됩니다. 안좋다. 둘째, 작업이 int 레벨에 있었을 때 오랫동안 시행되므로 소형 CPU에서는 매우 비효율적으로 작동합니다. 셋째, 함수형 매크로는 모든 악의 근원입니다. 어떠한 유형의 안전성도 없습니다. 또한 과제 없음에 대한 이전 의견은 매우 유효합니다.
룬딘

2
경우에 실패합니다 arg입니다 long long. 1L가장 넓은 유형이어야합니다 (uintmax_t)1. (당신은 도망 갈 수 있습니다 1ull)
MM

코드 크기를 최적화 했습니까? Intel 주류 CPU에서는 EAX의 8 비트 구성 요소를 작성하기 때문에이 함수가 반환 된 후 AX 또는 EAX를 읽을 때 부분 레지스터 중단이 발생합니다. (AMD CPU 또는 전체 레지스터와 별도로 부분 레지스터의 이름을 바꾸지 않는 다른 CPU에서는 문제가 없습니다. Haswell / Skylake는 AL을 개별적으로 이름을 바꾸지 않지만 AH로 이름을 바꿉니다. )
Peter Cordes

37

비트 연산자를 사용하십시오. & |

마지막 비트를 설정하려면 000b:

foo = foo | 001b

마지막 비트를 확인하려면 foo:

if ( foo & 001b ) ....

마지막 비트를 지우려면 foo:

foo = foo & 110b

나는 XXXb명확성을 위해 사용 했다. 비트를 패킹하는 데이터 구조에 따라 HEX 표현으로 작업하고있을 것입니다.


7
C에는 이진 표기법이 없습니다. 이진 정수 상수는 비표준 확장입니다.
Lundin

XOR을 사용하여 비트를 토글하십시오.foo = foo ^ MY_MASK
Peter L

마스크를 뒤집어 지우지 않으려면 NOT을 사용하십시오.foo = foo & ~MY_MASK
Peter L

32

초보자에게는 예를 들어 조금 더 설명하고 싶습니다.

예:

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)

26

여기에서 부호없는 정수 배열의 모든 유형의 작동 내가 좋아하는 비트 연산 매크로의 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, &)) ...

기타


5
읽는 것이 좋지만 가능한 부작용에 대해 알고 있어야합니다. BITOP(array, bit++, |=);루프에서 사용 하면 발신자가 원하는 것을 수행하지 않을 가능성이 높습니다.
foraidt

과연. 당신이 선호 할 수 =) 하나의 변종 배열 요소 제자리에 비트를 이동하기위한 다른 주소에 대한 2 개 매크로, 1로를 분리하는 것입니다, ALA BITCELL(a,b) |= BITMASK(a,b);(모두 테이크 a인수로는 크기를 결정하지만, 후자는 평가하지 않을 것 a때문에 sizeof) 에만 나타납니다 .
R .. GitHub 중지 지원 얼음

1
@R ..이 답변은 실제로 오래되었지만이 경우 매크로보다 함수를 선호합니다.
PC Luddite

마이너 : 3 (size_t)캐스트가 될 일부 보장하는 것 부호 수학을 함께 %. (unsigned)거기 에요
chux-복원 모니카

(size_t)(b)/(8*sizeof *(a))불필요하게는 축소 할 수 b분할하기 전에. 매우 큰 비트 배열에만 문제가 있습니다. 여전히 흥미로운 매크로입니다.
chux-Reinstate Monica

25

"embedded"태그가 붙어 있으므로 마이크로 컨트롤러를 사용한다고 가정하겠습니다. 위의 모든 제안은 유효하며 작동합니다 (읽기-수정-쓰기, 공용체, 구조체 등).

그러나 오실로스코프 기반 디버깅이 진행되는 동안 이러한 방법이 마이크로의 PORTnSET / PORTnCLEAR 레지스터에 직접 값을 쓰는 것과 비교할 때 CPU 사이클에서 상당한 오버 헤드가 있다는 사실에 놀랐습니다. 주파수 ISR의 토글 핀.

익숙하지 않은 사람들을 위해 : 나의 예에서, 마이크로는 출력 핀을 반영하는 일반적인 핀 상태 레지스터 PORTn을 가지고 있으므로, PORTn | = BIT_TO_SET을 수행하면 해당 레지스터에 대한 읽기-수정-쓰기가 발생합니다. 그러나 PORTnSET / PORTnCLEAR 레지스터는 "이 비트를 1로 설정하십시오"(SET) 또는 "이 비트를 0으로 설정하십시오"(CLEAR)를 의미하고 "0"은 "핀을 그대로 두십시오"를 의미하는 '1'을 사용합니다. 따라서 비트를 설정 또는 해제하는지 (항상 편리하지는 않지만) 훨씬 빠른 반응 및 작은 조립 코드에 따라 두 개의 포트 주소가 생깁니다 .


Micro는 Codewarrior에서 C를 사용하여 Coldfire MCF52259였습니다. 디스어셈블러 / asm을 보면 CPU가 가장 기본적인 작업을 수행하기 위해 수행해야하는 모든 단계가 표시되므로 유용한 연습입니다. <br> 우리는 또한 시간이 중요한 루프에서 다른 CPU 호깅 명령어를 발견했습니다. var % = max_val을 사용하여 변수를 제한하면 매번 CPU 사이클의 더미 비용이 발생하지만 if (var> max_val) var- = max_val 만 사용 몇 가지 지침. <br> 몇 가지 트릭에 대한 유용한 안내서는 다음과 같습니다. codeproject.com/Articles/6154/…
John U

더욱 중요한 것은 도우미 메모리 매핑 I / O 레지스터는 원자 업데이트를위한 메커니즘을 제공한다는 것입니다. 시퀀스가 중단되면 읽기 / 수정 / 쓰기가 매우 나빠질 수 있습니다.
벤 Voigt

1
모든 포트 레지스터는로 정의 volatile되므로 컴파일러는 해당 레지스터와 관련된 코드에서 최적화를 수행 할 수 없습니다. 따라서 이러한 코드를 분해하고 어셈블러 수준에서 어떻게 작동하는지 확인하는 것이 좋습니다.
Lundin

24

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

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라고 생각하지만 구현에 따라 다를 수 있습니다. 또한 컴파일러가 바이트 경계를 넘는 필드를 처리하는 방법을 확인하십시오.

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


2
비트 필드에 대한 거의 모든 것이 구현 정의되어 있습니다. 특정 컴파일러가 구현하는 방법에 대한 모든 세부 정보를 찾을 수 있다고해도 코드에서 해당 컴파일러를 사용하면 이식 할 수 없게됩니다.
Lundin

1
@Lundin-사실이지만 임베디드 시스템 비트-fidled (특히 하드웨어 레지스터, 내 대답과 관련이 있음)는 어쨌든 유용하게 이식 될 수 없습니다.
Roddy

1
완전히 다른 CPU 사이에는 없습니다. 그러나 대부분 컴파일러와 다른 프로젝트간에 이식성이 있기를 원할 것입니다. 그리고 데이터 프로토콜 인코딩 / 디코딩과 같이 하드웨어와 전혀 관련이없는 임베디드 "비트-피들 링"이 많이 있습니다.
룬딘

... 내장 프로그래밍을 수행하는 비트 필드를 사용하는 습관을들이는 경우 X86 코드가 더 빨라지고 더 빠릅니다. 전체 벤치 마크가 필요한 간단한 벤치 마크가 아니라 프로그램이 리소스를 놓고 경쟁하는 실제 멀티 태스킹 환경에 있습니다. CISC의 장점-원래 설계 목표는 버스보다 느린 CPU 및 느린 메모리를 보완하는 것입니다.

20

임의 유형의 변수에서 임의의 위치에서 비트를 확인하십시오.

#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을 사용하여 테스트했습니다. 비트를 설정하고 지우는 비슷한 매크로를 만들 수 있습니다. 이 솔루션과 다른 많은 솔루션의 주요 차이점은 거의 모든 유형의 변수에서 모든 위치에서 작동한다는 것입니다.


20

임의 크기의 비트 맵의 ​​경우 더 일반적입니다.

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

2
CHAR_BIT에 의해 이미 정의되었으므로 limits.h직접 입력 할 필요는 없습니다 BITS(실제로 코드를 더 나쁘게 만들 수도 있습니다)
MM

14

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

14

많은 비트를 돌리고 있다면 마스크를 사용하여 모든 것을 빠르게 할 수 있습니다. 다음 함수는 매우 빠르고 유연합니다 (모든 크기의 비트 맵에서 비트 트위들 링 허용).

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 등이 리틀 엔디안 프로세서의 경우 메모리에서 서로 올바르게 매핑됩니다 (작은 엔디안 프로세서가 빅 엔디안 프로세서보다 '더 나은'것입니다) 의 위에...).


2
단일 연산자로 구현할 수있는 함수에 테이블을 사용하지 마십시오. TQuickByteMask [n]은 (1 << n)과 같습니다. 또한 논증을 짧게하는 것은 매우 나쁜 생각입니다. / 및 %는 실제로 비트 쉬프트 / 비트가 아닌 나눗셈이되며 2의 거듭 제곱으로 부호있는 나누기는 비트 단위로 구현할 수 없기 때문입니다. 인수 유형을 부호없는 int로 만들어야합니다!
R .. GitHub 중지 지원 얼음

이게 요점이 뭐야? 코드를 느리게 읽기 어렵게 만듭니다. 나는 그것으로 하나의 장점을 볼 수 없습니다. 1u << n은 C 프로그래머가 읽기 쉽고, 단일 클럭 틱 CPU 명령으로 변환 될 수 있기를 바랍니다. 반면에, 귀하의 부서는 특정 아키텍처가 부서를 제대로 처리하지 못하는 정도에 따라 약 10 틱 또는 최대 100 틱까지 나쁘게 변환됩니다. 비트 맵 기능의 경우 속도를 최적화하기 위해 각 비트 인덱스를 바이트 인덱스로 변환하는 룩업 테이블을 갖는 것이 더 합리적입니다.
Lundin

2
big / little endian의 경우 big endian은 정수와 원시 데이터 (예 : 문자열)를 동일한 방식으로 전체 비트 맵에서 왼쪽에서 오른쪽으로 msb에서 lsb로 매핑합니다. 리틀 엔디안은 정수를 왼쪽에서 오른쪽으로 7-0, 15-8, 23-18, 31-24로 매핑하지만 원시 데이터는 여전히 왼쪽에서 오른쪽으로 msb는 lsb입니다. 따라서 특정 알고리즘에 작은 엔디안이 더 나은 방법은 완전히 저를 넘어서는 것입니다.
Lundin

2
@R .. 테이블은 구형 마이크로 칩 MCU와 같이 플랫폼이 효율적으로 이동할 수없는 경우에 유용 할 수 있지만 물론 샘플의 분할은 절대적으로 비효율적입니다.
jeb

12

이것을 사용하십시오 :

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

    return num;
}

5
비효율적 인 분기를 사용합니다.
asdf

3
@asdf 컴파일러의 일은 가장 효율적인 바이너리를 출력하는 것이고, 프로그래머는 명확한 코드를 작성하는 것입니다
MM

3
이것은 테스트, 설정 및 특정 비트 지우기에 대한 좋은 데모입니다. 그러나 약간 토글하기에는 매우 나쁜 방법입니다.
벤 Voigt

10

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

10

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


9

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설정 및 지우기 부울을 쉽게하십시오.

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

//  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 개월 후 데이터를 수집 한 메인 프레임 시스템이 실제로 오작동하고 있음을 증명했습니다. 비트 배열의 단순성으로 인해 검색 접근 방식과 비교하여 정확성이 매우 높습니다.


표준 : 비트 세트는 실제로 대부분의 컴파일러에 의해 비트로 구현
galinette

@galinette, 동의합니다. 헤더 파일 #include <bitset>은 이와 관련하여 좋은 리소스입니다. 또한 벡터 크기를 변경해야하는 경우에 대한 특수 클래스 vector <bool> C ++ STL, 2 판, Nicolai M. Josuttis는 각각 pgs 650과 281에서 철저하게 다루고 있습니다. C ++ 11은 std :: bitset에 몇 가지 새로운 기능을 추가합니다. 나에게 특별한 관심은 비 순서 컨테이너의 해시 함수입니다. 고마워요! 내 뇌졸중 설명을 삭제하겠습니다. 이미 웹에 충분한 쓰레기가 있습니다. 나는 그것을 추가하고 싶지 않습니다.

3
이것은 각각에 대해 적어도 전체 바이트의 스토리지를 사용합니다 bool. int구현 하는 데 사용 되는 C89 설정의 경우 4 바이트 일 수도 있습니다.bool
MM

@MattMcNabb, 맞습니다. C ++에서 부울을 구현하는 데 필요한 int 유형의 크기는 표준에 의해 지정되지 않았습니다. 나는이 답변이 얼마 전에 잘못되었다는 것을 깨달았지만 사람들이 분명히 유용하다고 생각하면서 여기에 남겨두기로 결정했습니다. 비트 galinette의 의견을 사용하려는 사람들에게 여기 내 비트 라이브러리가 가장 도움이됩니다 ... stackoverflow.com/a/16534995/1899861

2
@RocketRoy : 아마도 이것이 "비트 연산"의 예라고 주장하는 문장을 바꿀 가치가있을 것입니다.
벤 Voigt

6

여기에 정의 된대로 연산자 중 하나를 사용 하십시오 .

사용되는 비트 설정할 바이너리 형태 비트 위치이다.int x = x | 0x?;?


2
0x이진수가 아닌 16 진수로 리터럴의 접두사입니다.
벤 Voigt

5

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

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)

5

사용 된 변수

int value, pos;

value-Data
pos-설정, 지우기 또는 토글하고자하는 비트의 위치.

조금 설정하십시오 :

value = value | 1 << pos;

조금만 지우십시오.

value = value & ~(1 << pos); 

조금 토글 :

value = value ^ 1 << pos;

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

의 반환 유형이 check_nth_bit될 수 있습니다 bool.
Xeverous

@Xeverous 네, 그것은 발신자의 의도에 달려 있습니다
Sazzad Hissain Khan

5


num = 55Integer에서 비트 단위 연산 (설정, 가져 오기, 지우기, 토글)을 수행하기 위해 가장 먼저 몇 가지를 가정 해 봅시다 .
n = 4비트 단위 연산을 수행하는 0 기반 비트 위치.

조금 얻는 방법?

  1. nth숫자 오른쪽 시프트 num, 비트 를 얻으려면 n. 그런 다음 &1로 비트 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 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. 왼쪽 시프트 1, n시간 1 << n.
  2. 위 결과로 비트 단위 보수를 수행하십시오. 따라서 n 번째 비트는 설정되지 않고 나머지 비트는 설정 ~ (1 << n)됩니다.
  3. 마지막으로 &위의 결과와로 비트 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 ^연산자를 사용합니다. 비트 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)

권장 자료- 비트 단위 연산자 연습


자세한 설명을 주셔서 감사합니다. 여기 BIT 매직에 대한 연습 문제에 대한 링크입니다 링크
찬드라 셰 카르

4

단일 비트를 어떻게 설정하고 지우고 토글합니까?

마스크를 형성하려고 할 때 일반적인 코딩 함정을 해결하려면
1항상 충분히 넓지는 않습니다.

number보다 넓은 유형의 경우 어떤 문제가 발생 1합니까? 정의되지 않은 동작 (UB)으로 이어지는
x변화에 비해 너무 클 수 있습니다 . 너무 크지 않더라도 가장 중요한 비트를 충분히 뒤집지 않을 수 있습니다.1 << xx~

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

와 작업에 대부분의 비트 조작, 최고의와 마찬가지로 서명되지 않은 유형이 아닌 서명 것들


오래된 질문에 대한 재미있는 모습! 부호있는 유형의 부호 비트를 설정하는 number |= (type_of_number)1 << x;것도 number |= (number*0 + 1) << x;적절 하지도 않습니다 ... 사실, 어느 것도 아닙니다 number |= (1ull << x);. 위치별로 휴대 할 수있는 방법이 있습니까?
chqrlie

1
@chqrlie IMO, 부호 비트 설정을 피하고 시프트로 UB 또는 IDB를 위험에 빠뜨리는 가장 좋은 방법은 부호없는 유형 을 사용하는 것 입니다. 이식성이 뛰어난 시프트 서명 코드는 너무 복잡하여 수용 할 수 없습니다.
chux-복원 모니카

3

C ++ 11 템플릿 버전 (헤더에 넣음) :

namespace bit {
    template <typename T1, typename T2> inline void set  (T1 &variable, T2 bit) {variable |=  ((T1)1 << bit);}
    template <typename T1, typename T2> inline void clear(T1 &variable, T2 bit) {variable &= ~((T1)1 << bit);}
    template <typename T1, typename T2> inline void flip (T1 &variable, T2 bit) {variable ^=  ((T1)1 << bit);}
    template <typename T1, typename T2> inline bool test (T1 &variable, T2 bit) {return variable & ((T1)1 << bit);}
}

namespace bitmask {
    template <typename T1, typename T2> inline void set  (T1 &variable, T2 bits) {variable |= bits;}
    template <typename T1, typename T2> inline void clear(T1 &variable, T2 bits) {variable &= ~bits;}
    template <typename T1, typename T2> inline void flip (T1 &variable, T2 bits) {variable ^= bits;}
    template <typename T1, typename T2> inline bool test_all(T1 &variable, T2 bits) {return ((variable & bits) == bits);}
    template <typename T1, typename T2> inline bool test_any(T1 &variable, T2 bits) {return variable & bits;}
}

이 코드는 깨졌습니다. (또한 ;함수 정의 후에 왜
그런가요

@melpomene 코드가 손상되지 않았으므로 테스트했습니다. 컴파일되지 않거나 결과가 잘못되었음을 의미합니까? 여분의 ';'에 대하여 기억 나지 않습니다. 실제로 제거 할 수 있습니다.
Joakim L. Christiansen

(variable & bits == bits)?
melpomene

주목 해 주셔서 감사합니다.((variable & bits) == bits)
Joakim L. Christiansen

std::bitsetc ++ 11에서 사용
pqnet

0

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

-2

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

value << n정의되지 않은 동작이 발생할 수 있습니다
MM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.