C/C++检查是否设置了一个位,即int变量

Mil*_*lan 98 c c++ bit-manipulation

int temp = 0x5E; // in binary 0b1011110.
Run Code Online (Sandbox Code Playgroud)

有没有这种方法可以检查temp中的第3位是1还是0而没有位移和屏蔽.

只是想知道是否有一些内置功能,或者我自己不得不写一个.

mou*_*iel 154

在C中,如果要隐藏位操作,可以编写一个宏:

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
Run Code Online (Sandbox Code Playgroud)

并以这种方式使用它:

CHECK_BIT(temp, n - 1)
Run Code Online (Sandbox Code Playgroud)

在C++中,您可以使用std :: bitset.

  • @Eduard:在C中,所有`!= 0`都是真的,为什么要这么麻烦?`1`与`0.1415`完全一样! (9认同)
  • 呃,`std :: bitset`,真的吗?当然,不是做一点工作(可能还有一些非常好的模板)来检查一个位,而是使用一个膨胀的容器来存储(在我的实现中)每个'bit'在一个原本未使用的`unsigned long`中.多么浪费空间! (4认同)
  • 如果你需要一个简单的真值,它应该是!!((var)&(1 <<(pos))). (3认同)
  • 确实使用std :: bitset. (3认同)
  • 在C中这很好.但是这种C++中的宏.那是可怕的,如此开放的滥用.使用std :: bitset (2认同)
  • @Christoph 您会发现何时有人执行了“typedef char BOOL”之类的操作,并且您尝试将 CHECK_BIT 的输出作为 BOOL 参数传递,而该参数恰好在第 8 个参数之后检查了一下。追踪并导致至少一个大规模的安全漏洞是一个非常棘手的错误。总是压扁你的布尔值。(或使用 stdbool.h) (2认同)

Joa*_*lva 82

检查是否设置了位N(从0开始):

temp & (1 << N)
Run Code Online (Sandbox Code Playgroud)

没有内置功能.

  • 提及它的+1从0开始,因为我怀疑OP正在考虑从1开始,接受的答案会让他遇到麻烦.:) (14认同)
  • 好的,我知道了.我们从0号开始,即"1 << 0",它是1,没有任何移位(移位0),这是"1 << 0 == 1" (6认同)

use*_*714 24

如果它是C++,我会使用std :: bitset.简单.直截了当.没有机会犯愚蠢的错误.

typedef std::bitset<sizeof(int)> IntBits;
bool is_set = IntBits(value).test(position);
Run Code Online (Sandbox Code Playgroud)

或者这种愚蠢

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);
Run Code Online (Sandbox Code Playgroud)

  • @ user21714我想你的意思是std :: bitset <8*sizeof(int)> (4认同)
  • upvote for template metaprogramming approach :) (2认同)
  • @iNFINITEi `std::bitset&lt;CHAR_BIT * sizeof(int)&gt;` 更正确 (2认同)

sho*_*r92 12

选择的答案实际上做错了什么.以下函数将返回位位置或0,具体取决于该位是否实际启用.这不是海报所要求的.

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
Run Code Online (Sandbox Code Playgroud)

这是海报最初寻找的内容.如果该位有效,则下面的函数将返回1或0,而不是位置.

#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
Run Code Online (Sandbox Code Playgroud)

  • 我花了一些时间才明白你的意思。更准确地说:如果位被设置,第一个函数返回 2 位位置的幂,否则返回 0。 (2认同)
  • 这正是我在使用它时遇到的确切问题,如“bool has_feature = CHECK_BIT(register, 25);”,很高兴知道我可以在没有双重否定的情况下做到这一点。 (2认同)

gim*_*mel 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)
    /* ... */
Run Code Online (Sandbox Code Playgroud)

此外,还有一个警告:

然而,结构中的位成员具有实际缺点.首先,内存中位的排序取决于体系结构,内存填充规则因编译器而异.此外,许多流行的编译器生成用于读写位成员的低效代码,并且由于大多数机器无法操作内存中的任意位组,因此存在与位域相关的严重线程安全问题(尤其是在多处理器系统上).但必须加载并存储整个单词.


Mr.*_*Ree 11

是的,我知道我没有"这样做".但我经常写:

    /* 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); }
Run Code Online (Sandbox Code Playgroud)

例如:

IsBitSet( foo, BIT(3) | BIT(6) );  // Checks if Bit 3 OR 6 is set.
Run Code Online (Sandbox Code Playgroud)

除此之外,这种方法:

  • 容纳8/16/32/64位整数.
  • 在我不知情和同意的情况下检测IsBitSet(int32,int64)调用.
  • 内联模板,因此没有函数调用开销.
  • const和引用,因此不需要复制/复制任何内容.我们保证编译器会接收任何试图改变参数的拼写错误.
  • 0!=使代码更清晰明了.编写代码的主要目的始终是与其他程序员清晰有效地沟通,包括那些技能较低的程序员.
  • 虽然不适用于这种特殊情况......通常,模板化函数避免了多次评估参数的问题.某些#define宏的已知问题.
    例如:#define ABS(X)(((X)<0)? - (X):( X))
          ABS(i ++);


Mar*_*ork 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,但是我认为发问者(和来自Google搜索的人)可能没有这种能力,您的回答可能会误导他们。 (2认同)

小智 5

#define CHECK_BIT(var,pos) ((var>>pos) & 1)
Run Code Online (Sandbox Code Playgroud)

pos - 从 0 开始的位位置。

返回 0 或 1。