C / C ++에서 1 비트가 설정되었는지 확인합니다. 즉, int 변수


100
int temp = 0x5E; // in binary 0b1011110.

비트 시프트 및 마스킹없이 temp의 비트 3이 1 또는 0인지 확인하는 방법이 있습니까?

이것에 대한 내장 함수가 있는지 알고 싶거나 직접 작성해야합니다.

답변:


157

C에서 비트 조작을 숨기려면 매크로를 작성할 수 있습니다.

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

이 방법을 사용 하여 오른쪽 끝에서 n 번째 비트 를 확인합니다 .

CHECK_BIT(temp, n - 1)

C ++에서는 std :: bitset을 사용할 수 있습니다 .


3
단순한 진리 값이 필요한 경우 !! ((var) & (1 << (pos)))이어야합니다.
Eduard-Gabriel Munteanu

10
@Eduard : C에서는 모든 != 0것이 사실이므로 왜 귀찮게합니까? 1는 정확히 0.1415!
Christoph

1
그리고 C ++를 사용하는 경우 매크로 대신 템플릿을 작성할 수 있습니다. :)
jalf

2
C에서는 괜찮습니다. 그러나 이러한 종류의 C ++ 매크로. 그것은 끔찍하고 남용의 여지가 있습니다. std :: bitset 사용
Martin York

5
어, std::bitset정말? 물론, 단일 비트를 확인하기 위해 약간의 작업 (그리고 잠재적으로 정말 멋진 템플릿)을 수행하는 대신 각 '비트'를 사용하지 않는 unsigned long. 공간 낭비입니다!
underscore_d

86

비트 N (0부터 시작)이 설정되었는지 확인합니다.

temp & (1 << N)

이를위한 내장 기능이 없습니다.


16
나는 OP가 1 기반이라고 생각하고 수락 된 답변이 그를 문제에 빠뜨릴 것이라고 생각하기 때문에 0에서 시작한다고 언급하는 데 +1입니다. :)
Jim Buck

흠. 0부터 시작하는 이유는 무엇입니까? 언제 우리는 무엇을 얻습니까 1 << 0?? 죄송합니다.
Danijel

6
알겠습니다. 우리는 0 번째 위치에서 시작합니다. 즉 1<<0, 교대가없는 1 인 (Shift 0)1<<0 == 1
Danijel

27

C ++ 인 경우 std :: bitset을 사용합니다. 단순한. 똑바로. 어리석은 오류의 가능성이 없습니다.

typedef std::bitset<sizeof(int)> IntBits;
bool is_set = IntBits(value).test(position);

또는이 어리 석음은 어떻습니까

template<unsigned int Exp>
struct pow_2 {
    static const unsigned int value = 2 * pow_2<Exp-1>::value;
};

template<>
struct pow_2<0> {
    static const unsigned int value = 1;
};

template<unsigned int Pos>
bool is_bit_set(unsigned int value)
{
    return (value & pow_2<Pos>::value) != 0;
} 

bool result = is_bit_set<2>(value);

4
@ user21714 나는 u 의미 std :: bitset <8 * sizeof (int)>
iNFINITEi

또는 std :: numeric_limits <int> :: digits
Léo Lam

@iNFINITEi은 std::bitset<CHAR_BIT * sizeof(int)>훨씬 더 정확합니다
Xeverous

13

그래, 내가하지 않습니다 알고 "이" 이런 식으로 할 수 있습니다. 그러나 나는 보통 다음과 같이 씁니다.

    /* Return type (8/16/32/64 int size) is specified by argument size. */
template<class TYPE> inline TYPE BIT(const TYPE & x)
{ return TYPE(1) << x; }

template<class TYPE> inline bool IsBitSet(const TYPE & x, const TYPE & y)
{ return 0 != (x & y); }

예 :

IsBitSet( foo, BIT(3) | BIT(6) );  // Checks if Bit 3 OR 6 is set.

무엇보다도이 접근 방식은 다음과 같습니다.

  • 8/16/32/64 비트 정수를 수용합니다.
  • 본인 모르게 동의없이 IsBitSet (int32, int64) 호출을 감지합니다.
  • 인라인 템플릿이므로 오버 헤드를 호출하는 함수가 없습니다.
  • const & 참조이므로 복제 / 복사 할 필요 가 없습니다 . 그리고 우리는 컴파일러가 인수를 변경하려는 오타를 선택한다는 것을 보장합니다.
  • 0! = 코드를 더 명확하고 명확하게 만듭니다. 코드 작성의 주된 요점은 항상 기술이 부족한 프로그래머를 포함하여 다른 프로그래머와 명확하고 효율적으로 통신하는 것입니다.
  • 이 특정 경우에는 적용 할 수 없지만 일반적으로 템플릿 함수는 인수를 여러 번 평가하는 문제를 방지합니다. 일부 #define 매크로의 알려진 문제입니다.
    예 : #define ABS (X) (((X) <0)?-(X) : (X))
          ABS (i ++);

13

선택한 답변이하는 일은 실제로 잘못되었습니다. 아래 함수는 비트가 실제로 활성화되었는지 여부에 따라 비트 위치 또는 0을 반환합니다. 이것은 포스터가 요구 한 것이 아닙니다.

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

포스터가 원래 찾고 있던 것이 여기 있습니다. 아래 함수는 비트가 활성화되고 위치가 아닌 경우 1 또는 0을 반환합니다.

#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)

1
무슨 뜻인지 이해할 때까지 시간이 좀 걸렸습니다. 보다 정확하게 : 첫 번째 함수는 비트가 설정되어 있으면 비트 위치의 거듭 제곱으로 2를 반환하고 그렇지 않으면 0을 반환합니다.
lukasl1991

1
이것은 내가 bool has_feature = CHECK_BIT(register, 25);이중 부정 없이도 할 수 있다는 것을 아는 것이 좋다와 같이 사용하는 동안 방금 만난 정확한 문제 입니다.
Jimmio92

11

이 비트 필드 설명에 따르면 필드를 직접 정의하고 액세스하는 방법이 있습니다. 이 항목의 예는 다음과 같습니다.

struct preferences {
    unsigned int likes_ice_cream : 1;
    unsigned int plays_golf : 1;
    unsigned int watches_tv : 1;
    unsigned int reads_books : 1;
}; 

struct preferences fred;

fred.likes_ice_cream = 1;
fred.plays_golf = 1;
fred.watches_tv = 1;
fred.reads_books = 0;

if (fred.likes_ice_cream == 1)
    /* ... */

또한 경고가 있습니다.

그러나 구조체의 비트 멤버에는 실질적인 단점이 있습니다. 첫째, 메모리의 비트 순서는 아키텍처에 따라 다르며 메모리 패딩 규칙은 컴파일러마다 다릅니다. 또한 널리 사용되는 많은 컴파일러는 비트 멤버를 읽고 쓰기 위해 비효율적 인 코드를 생성하며, 대부분의 컴퓨터가 메모리에서 임의의 비트 세트를 조작 할 수 없다는 사실로 인해 비트 필드 (특히 다중 프로세서 시스템에서)와 관련된 잠재적으로 심각한 스레드 안전 문제가 있습니다. 대신 전체 단어를로드하고 저장해야합니다.


6

Bitset- http ://www.cppreference.com/wiki/stl/bitset/start를 사용할 수 있습니다 .


5

std :: bitset 사용

#include <bitset>
#include <iostream>

int main()
{
    int temp = 0x5E;
    std::bitset<sizeof(int)*CHAR_BITS>   bits(temp);

    // 0 -> bit 1
    // 2 -> bit 3
    std::cout << bits[2] << std::endl;
}

1
여기서 언급 할 가치가있는 몇 가지 사항-비트 [3]은 LSB에서 MSB까지 세는 4 번째 비트를 제공합니다. 느슨하게 넣으려면 오른쪽에서 왼쪽으로 세는 4 비트를 제공합니다. 또한 sizeof (int)는 int의 문자 수를 제공하므로 std :: bitset <sizeof (int) * CHAR_BITS> bits (temp) 및 bits [sizeof (int) * CHAR_BITS-3]이어야합니다. MSB에서 LSB까지 세 번째 비트 계산을 테스트하는 것이 아마도 의도 일 것입니다.
plastic chris

2
예,하지만 질문자 (및 Google 검색에서 오는 사람들)는 해당 기술이 없을 수 있으며 귀하의 답변은 오해 할 수 있습니다.
plastic chris

이 대답은 끔찍합니다. 삭제해야합니다.
Adam Burry 2013

temp"빅 엔디안"으로 만들기 위해 값 을 반영 할 필요가 없습니까?
jww

4

즉, _bittest 내장 명령어가 있습니다.


3
링크는 "Microsoft 특정"을 나타냅니다. 코드를 이식 할 필요가없는 경우에만 사용하십시오.
mouviciel

링크는 "Microsoft 특정"을 나타내지 만 인텔 C ++ 컴파일러에서 가져온 내장 함수이며 결과적으로 BT 명령어가 생성되므로 인라인 어셈블러에서도 수행 할 수 있습니다. 물론 그렇다고해서 더 이식성이있는 것은 아닙니다.
Dave Van den Eynde

1
또한 x86 아키텍처에만 해당됩니다. 그래서 아니, 확실히 휴대용이 아닙니다.
jalf

다른 아키텍처에도 비슷한 옵션이 있다고 확신합니다.
Dave Van den Eynde

내장 함수의 핵심은 하드웨어가있는 경우 하드웨어를 활용하고 하드웨어가 처리하지 않는 경우 소프트웨어 교체를 사용한다는 것입니다.
Eclipse

4

나는 이것을 사용한다 :

#define CHECK_BIT(var,pos) ( (((var) & (pos)) > 0 ) ? (1) : (0) )

여기서 "pos"는 2 ^ n (ig 1,2,4,8,16,32 ...)으로 정의됩니다.

반환 값 : 참이면 1 거짓이면 0


2
나는 이것이 C와 C ++ 모두에 대한 유일한 정답이라고 생각합니다. "... 비트 시프트 및 마스킹없이" 요구 사항을 준수 하는 유일한 제품입니다 . 4 = 2^(3-1)질문의 일부 였으므로 비트 위치 3에 대해 사용하도록 명시 적으로 명시해야합니다 .
jww

3

PDF의 개체에 대한 플래그를 정의한 32 비트 정수를 읽으려고했는데 이것이 저에게 작동하지 않았습니다.

수정 사항은 정의를 변경하는 것입니다.

#define CHECK_BIT(var,pos) ((var & (1 << pos)) == (1 << pos))

피연산자는 & 둘 다 1에있는 플래그와 함께 정수를 반환하고 부울로 제대로 캐스팅되지 않았습니다.


!= 0똑같이 할 것입니다. 생성 된 기계 명령어가 어떻게 다를 수 있는지 모릅니다.
Adam Burry

2

시프트 및 마스킹을 "시뮬레이션"할 수 있습니다. if ((0x5e / (2 * 2 * 2)) % 2) ...


목록을 무작위로 섞고 현재 "정렬"되었는지 테스트하여 정렬 할 수 있습니다. 예 : while (/ * NOT * /! isSorted ()) {RandomlyShuffle (); }하지만 우리는 ...
Mr. Ree

이 솔루션은 리소스를 낭비하고 직관적이지 않습니다. div, muls 및 mods는 가장 비싼 세 가지 기능입니다. 비교 테스트에 의해 ands 및 shifts가 가장 저렴합니다. 일부는 실제로 5주기 미만으로 완료 될 수 있습니다.
jheriko

그럴 수도 있습니다 (현대 프로세서는 비트와 점프를 싫어하기 때문입니다). OP는 원래 "비트 이동 및 마스킹이없는"솔루션을 명시 적으로 요청했습니다 . 따라서 일치하지만 느린 대답에 대해 더 많은 부정적인 점을 제공하십시오. OP가 마음을 바꿨다고 게시물을 삭제하지는 않겠습니다.
Leonidas

까다로워 보입니다. 이 답변에 투표하지 마십시오. 때로는 다른 뷰를 탐색하는 것이 좋습니다.
Viet


1

이렇게 간단한 것을 사용하지 않겠습니까?

uint8_t status = 255;
cout << "binary: ";

for (int i=((sizeof(status)*8)-1); i>-1; i--)
{
  if ((status & (1 << i)))
  {
    cout << "1";
  } 
  else
  {
    cout << "0";
  }
}

출력 : 바이너리 : 11111111


삼항으로 쉽게 할 수 있다면 : std::cout << (((status & (1 << i)) ? '1' : '0');. 당신은 사용해야 CHAR_BIT에서 상수를 <climits>이 경우에 당신은 결과를 알고 있지만 당신이 사용하고 있기 때문에 어쨌든 8 될 것 대신에 하드 코딩 8 비트uint8_t
라이언 이닝

0

진짜 하드 코딩 된 방법을 원한다면 :

 #define IS_BIT3_SET(var) ( ((var) & 0x04) == 0x04 )

이 hw 종속적이며이 비트 순서가 7654 3210이고 var가 8 비트라고 가정합니다.

#include "stdafx.h"
#define IS_BIT3_SET(var) ( ((var) & 0x04) == 0x04 )
int _tmain(int argc, _TCHAR* argv[])
{
    int temp =0x5E;
    printf(" %d \n", IS_BIT3_SET(temp));
    temp = 0x00;
    printf(" %d \n", IS_BIT3_SET(temp));
    temp = 0x04;
    printf(" %d \n", IS_BIT3_SET(temp));
    temp = 0xfb;
    printf(" %d \n", IS_BIT3_SET(temp));
    scanf("waitng %d",&temp);

    return 0;
}

결과 :

1010


1
& 연산은 내부 표현이 아닌 값에서 수행됩니다.
Remo.D

안녕하세요 Remo.D-귀하의 의견을 이해하지 못하셨습니까? 잘 작동하는 'c'코드를 포함했습니다.
사이먼

그의 요점은 하드웨어 의존적이지 않다는 것입니다. IS_BIT3_SET은 항상 4 번째 최하위 비트를 테스트합니다
Eclipse

0

지금 대답하기에는 꽤 늦었지만, 간단히 POWER 및 MODULUS 수학 연산자를 사용하여 N 번째 비트가 설정되었는지 여부를 찾을 수있는 간단한 방법이 있습니다.

'temp'에 N 번째 비트가 설정되어 있는지 알고 싶다고 가정 해 보겠습니다. 다음 부울 표현식은 비트가 설정되면 true를, 그렇지 않으면 0을 제공합니다.

  • (temp MODULUS 2 ^ N + 1> = 2 ^ N)

다음 예를 고려하십시오.

  • int 온도 = 0x5E; // 바이너리 0b1011110 // BIT 0은 LSB입니다.

세 번째 비트가 설정되어 있는지 알고 싶다면

  • (94 모듈러스 16) = 14> 2 ^ 3

따라서 expression은 3 번째 비트가 설정되었음을 나타내는 true를 반환합니다.


0

한 가지 접근 방식은 다음 조건 내에서 확인합니다.

if ( (mask >> bit ) & 1)

설명 프로그램은 다음과 같습니다.

#include <stdio.h>

unsigned int bitCheck(unsigned int mask, int pin);

int main(void){
   unsigned int mask = 6;  // 6 = 0110
   int pin0 = 0;
   int pin1 = 1;
   int pin2 = 2;
   int pin3 = 3;
   unsigned int bit0= bitCheck( mask, pin0);
   unsigned int bit1= bitCheck( mask, pin1);
   unsigned int bit2= bitCheck( mask, pin2);
   unsigned int bit3= bitCheck( mask, pin3);

   printf("Mask = %d ==>>  0110\n", mask);

   if ( bit0 == 1 ){
      printf("Pin %d is Set\n", pin0);
   }else{
      printf("Pin %d is not Set\n", pin0);
   }

    if ( bit1 == 1 ){
      printf("Pin %d is Set\n", pin1);
   }else{
      printf("Pin %d is not Set\n", pin1);
   }

   if ( bit2 == 1 ){
      printf("Pin %d is Set\n", pin2);
   }else{
      printf("Pin %d is not Set\n", pin2);
   }

   if ( bit3 == 1 ){
      printf("Pin %d is Set\n", pin3);
   }else{
      printf("Pin %d is not Set\n", pin3);
   }
}

unsigned int bitCheck(unsigned int mask, int bit){
   if ( (mask >> bit ) & 1){
      return 1;
   }else{
      return 0;
   }
}

산출:

Mask = 6 ==>>  0110
Pin 0 is not Set
Pin 1 is Set
Pin 2 is Set
Pin 3 is not Set

0
#define CHECK_BIT(var,pos) ((var>>pos) & 1)

pos-0부터 시작하는 비트 위치.

0 또는 1을 반환합니다.


-1

나는 이것을 만든다 :

LATGbits.LATG0 = ((m & 0x8)> 0); // m의 비트 -2가 1인지 확인


-2

가장 빠른 방법은 마스크 조회 테이블 인 것 같습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.