C / C ++ ตรวจสอบว่ามีการตั้งค่าหนึ่งบิตหรือไม่เช่นตัวแปร int


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

มีวิธีตรวจสอบว่าบิต 3 ใน temp เป็น 1 หรือ 0 โดยไม่ต้องขยับและกำบังเล็กน้อยหรือไม่

แค่อยากรู้ว่ามีฟังก์ชันในตัวสำหรับสิ่งนี้หรือฉันถูกบังคับให้เขียนด้วยตัวเอง

คำตอบ:


159

ใน C หากคุณต้องการซ่อนการจัดการบิตคุณสามารถเขียนมาโคร:

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

และใช้วิธีนี้ในการตรวจสอบที่ n THบิตจากปลายขวา:

CHECK_BIT(temp, n - 1)

ใน C ++ คุณสามารถใช้มาตรฐาน :: bitset


86

ตรวจสอบว่าบิต N (เริ่มจาก 0) ถูกตั้งค่าไว้หรือไม่:

temp & (1 << N)

ไม่มีฟังก์ชัน builtin สำหรับสิ่งนี้


27

ฉันจะใช้ std :: bitset ถ้าเป็น C ++ เรียบง่าย ตรงไปตรงมา ไม่มีโอกาสสำหรับข้อผิดพลาดโง่ ๆ

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

14

สิ่งที่คำตอบที่เลือกทำนั้นผิดจริง ฟังก์ชั่นด้านล่างนี้จะคืนตำแหน่งบิตหรือ 0 ขึ้นอยู่กับว่าบิตนั้นถูกเปิดใช้งานจริงหรือไม่ นี่ไม่ใช่สิ่งที่ผู้โพสต์ขอ

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

นี่คือสิ่งที่ผู้โพสต์มองหาในตอนแรก ฟังก์ชันด้านล่างนี้จะส่งกลับค่า 1 หรือ 0 หากเปิดใช้งานบิตและไม่ใช่ตำแหน่ง

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

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

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

นอกจากนี้ยังมีคำเตือน:

อย่างไรก็ตามสมาชิกบิตในโครงสร้างมีข้อบกพร่องในทางปฏิบัติ ประการแรกการจัดลำดับบิตในหน่วยความจำขึ้นอยู่กับสถาปัตยกรรมและกฎการเติมหน่วยความจำจะแตกต่างกันไปในแต่ละคอมไพเลอร์ถึงคอมไพเลอร์ นอกจากนี้คอมไพเลอร์ยอดนิยมจำนวนมากยังสร้างโค้ดที่ไม่มีประสิทธิภาพสำหรับการอ่านและเขียนสมาชิกบิตและอาจมีปัญหาด้านความปลอดภัยของเธรดที่รุนแรงซึ่งเกี่ยวข้องกับฟิลด์บิต (โดยเฉพาะในระบบมัลติโปรเซสเซอร์) เนื่องจากเครื่องส่วนใหญ่ไม่สามารถจัดการกับชุดบิตในหน่วยความจำได้โดยพลการ แต่ต้องโหลดและเก็บทั้งคำแทน





4

ฉันใช้สิ่งนี้:

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

โดยที่ "pos" กำหนดเป็น 2 ^ n (ig 1,2,4,8,16,32 ... )

ส่งคืน: 1 ถ้าจริง 0 ถ้าเป็นเท็จ


3

ฉันพยายามอ่านจำนวนเต็ม 32 บิตซึ่งกำหนดแฟล็กสำหรับวัตถุใน PDF และสิ่งนี้ไม่ได้ผลสำหรับฉัน

สิ่งที่แก้ไขได้คือการเปลี่ยนการกำหนด:

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

ตัวถูกดำเนินการ & ส่งคืนจำนวนเต็มด้วยแฟล็กที่ทั้งสองมีเป็น 1 และไม่ได้ส่งไปยังบูลีนอย่างถูกต้องนี่เป็นเคล็ดลับ



2

สำหรับโซลูชันเฉพาะ x86 ระดับต่ำให้ใช้ x86 TEST opcode

คอมไพเลอร์ของคุณควรเปลี่ยน_bittestเป็นแม้ว่า ...


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


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

ผลลัพธ์ใน:

1 0 1 0


0

แม้ว่าจะค่อนข้างช้าที่จะตอบในตอนนี้ แต่มีวิธีง่ายๆที่สามารถค้นหาได้ว่ามีการตั้งค่าบิต N หรือไม่เพียงแค่ใช้ตัวดำเนินการทางคณิตศาสตร์ POWER และ MODULUS

สมมติว่าเราต้องการทราบว่า 'temp' มีการตั้งค่าบิต N หรือไม่ นิพจน์บูลีนต่อไปนี้จะให้เป็นจริงถ้าบิตถูกตั้งค่าเป็น 0 มิฉะนั้น

  • (โมดูลอุณหภูมิ 2 ^ N + 1> = 2 ^ N)

พิจารณาตัวอย่างต่อไปนี้:

  • อุณหภูมิ int = 0x5E; // ในไบนารี 0b1011110 // BIT 0 คือ LSB

ถ้าฉันต้องการทราบว่าบิตที่ 3 ถูกตั้งค่าหรือไม่ฉันจะได้รับ

  • (94 โมดูล 16) = 14> 2 ^ 3

ดังนั้นนิพจน์จะคืนค่าจริงโดยระบุว่าบิตที่ 3 ถูกตั้งค่า


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


-1

ฉันทำสิ่งนี้:

LATGbits.LATG0 = ((ม & 0x8)> 0); // เพื่อตรวจสอบว่า bit-2 ของ m เป็น 1 หรือไม่


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.