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)))にする必要があります。
エデュアルド-ガブリエルムンテアヌ

10
@エデュアルド:Cでは、すべて!= 0が正しいので、なぜわざわざ?1とまったく同じ0.1415です!
クリストフ

1
また、C ++を使用している場合は、マクロの代わりにテンプレートを作成できます(すべきです)。:)
jalf

2
Cではこれで問題ありません。しかし、C ++のこの種のマクロ。それは恐ろしいことであり、虐待の可能性があります。std :: bitsetを使用する
マーティンヨーク

5
ええと、std::bitset本当に?確かに、ほんの少しの作業(および場合によってはいくつかの本当に素晴らしいテンプレート)を実行して単一のビットをチェックするのではなく、(私の実装では)各 'ビット'を未使用の状態で格納する肥大化したコンテナーを使用しunsigned longます。なんてスペースの無駄だ!
underscore_d 2016年

86

ビットN(0から開始)が設定されているかどうかを確認します。

temp & (1 << N)

このための組み込み関数はありません。


16
OPが1ベースと考えていて、受け入れられた答えが彼を困らせるので、私はそれが0から始まっていることを言及するための+1。:)
ジムバック

うーん。なぜこれは0から始まるのですか?いつ何を手に入れます1 << 0か?すみません、混乱しています。
Danijel 2016

6
はい、わかった。我々は、第0 possitionから開始1<<0され、任意のシフトせずに1である、(シフト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私はあなたがstd :: bitset <8 * sizeof(int)>を意味していたと思います
iNFINITEi

またはSTD ::のnumeric_limits <整数> ::桁
レオ・ラム

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

また、警告があります:

ただし、構造体のビットメンバーには実用上の欠点があります。まず、メモリ内のビットの順序はアーキテクチャに依存し、メモリパディングルールはコンパイラごとに異なります。さらに、多くの一般的なコンパイラは、ビットメンバーの読み取りと書き込みに非効率的なコードを生成します。ほとんどのマシンはメモリ内の任意のビットセットを操作できないため、ビットフィールド(特にマルチプロセッサシステム)に関連するスレッドセーフの問題が発生する可能性があります。代わりに、単語全体を読み込んで保存する必要があります。



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までの3番目のビットのカウントをテストします。これはおそらく意図です。
プラスチック製のクリス、

2
はい、しかし、質問者(およびGoogle検索から来た人々)はそのスキルを持っていない可能性があり、あなたの回答がそれらを誤解させる可能性があると思います。
プラスチック製のクリス、

この答えはひどいです。削除する必要があります。
Adam Burry、2013年

temp「ビッグエンディアン」にするために値を反映する必要はありませんか?
jww 2018

4

つまり、_bittest組み込み命令があります。


3
リンクは「Microsoft固有」を示しています。コードを移植可能にする必要がない場合にのみ使用してください。
mouviciel

リンクは「Microsoft固有」を示していますが、これはIntel C ++コンパイラーから引き継がれた組み込み関数であり、BT命令になるため、インラインアセンブラーでも実行できます。もちろん、それによって移植性が向上するわけではありません。
Dave Van den Eynde、2009

1
また、x86アーキテクチャに固有です。ですから、絶対にポータブルではありません。
jalf

他のアーキテクチャにも同様のオプションがあると思います。
Dave Van den Eynde、2009

組み込みのまさにポイントは、ハードウェアが存在する場合はハードウェアを利用し、ハードウェアがハードウェアを処理しない場合はソフトウェアの代替を使用することです。
日食

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 2018

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、およびmodは、3つの最も高価な関数です。比較テストでは、andsとshiftが最も安価です。実際に5サイクル未満で実行できるものはいくつかあります。
jheriko 09

それは可能性があります(最新のプロセッサはビットとジャンプを嫌うため、そうではありません)。OPは当初、「ビットシフトとマスキングなしの」解決策を明示的に求めました。だから、一致しているが遅い答えのためにさらに否定的なポイントを与えてください。OPが気が変わったからといって、投稿を削除することはありません。
レオニダス

トリッキーに見えます。この回答には投票しないでください。時々、他のビューを探索することは良いことです。
Viet

2

低レベルのx86固有のソリューションでは、x86 TESTオペコードを使用します。

コンパイラは_bittestをこれに変換する必要があります...


BTはより良い方法でタスクに適合するため、テストよりもBTの方を好みます。
u_Ltd。

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 )

このハードウェアに依存し、このビット順序は7654 3210であり、変数は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;
}

結果:

1 0 1 0


1
&演算は、内部表現ではなく値に対して行われます。
Remo.D 2009

こんにちはRemo.D-私はあなたのコメントを理解できませんか?うまく機能する「c」コードをいくつか含めました。
サイモン、

彼のポイントは、ハードウェアに依存しないということです-IS_BIT3_SETは常に4番目の最下位ビットをテストします
Eclipse

0

今答えるのはかなり遅いですが、POWERとMODULUS数学演算子を使用するだけで、N番目のビットが設定されているかどうかを確認する簡単な方法があります。

「temp」にN番目のビットが設定されているかどうかを知りたいとしましょう。次のブール式は、ビットが設定されている場合はtrue、それ以外の場合は0になります。

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

次の例について考えてみます。

  • int temp = 0x5E; //バイナリ0b1011110で//ビット0はLSB

3番目のビットが設定されているかどうかを知りたい場合は、

  • (94 MODULUS 16)= 14> 2 ^ 3

したがって、式はtrueを返し、3番目のビットが設定されていることを示します。


0

1つのアプローチは、次の条件内でチェックすることです。

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.