better way to check bit in c

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Hi guys

I usually check a bit like this:
Code:
#define CHECK_BIT(data, pos)  ((var) & (1<<(pos)))

if (CHECK_BIT(data, 1){
  // do stuff
}

if (CHECK_BIT(data, 2){
  // do stuff
}

../
Is there a way to do something like that to make it look better??
Code:
switch(data){
  case bit_1:
    break;
  case bit_2:
    break;
....
}
 

dl324

Joined Mar 30, 2015
18,225
You could use bit fields in a struct and maybe a union. There may be some portability issues though...
 
Last edited:

WBahn

Joined Mar 31, 2012
32,711
Hi guys

I usually check a bit like this:
Code:
#define CHECK_BIT(data, pos)  ((var) & (1<<(pos)))

if (CHECK_BIT(data, 1){
  // do stuff
}

if (CHECK_BIT(data, 2){
  // do stuff
}

../
Is there a way to do something like that to make it look better??
Code:
switch(data){
  case bit_1:
    break;
  case bit_2:
    break;
....
}
Your switch idea won't work since if data has other bits set it won't match the case label.

The way you are doing it is probably about as efficient as you are going to get. By using a macro you are avoiding function-call overhead and most processors are very efficient at bit shift and bitwise operations.
 

MrSoftware

Joined Oct 29, 2013
2,273
The first method looks good functionally, and a really good compiler might even optimize out the shift since your shift values are hard coded. There's more than one right answer:

Code:
if( data & 0x08)  /* bit 4 */
if(data & 0b10000)  /* bit 5, if your compiler understands this syntax */

Or if you like more wordy code you could do it like this:

#define BIT1 0x01
#define BIT2 0x02
OR
#define BIT3 (1 << 2)  /* Compiler will probably optimize out the shift at compile time */
#define BIT4 (0b1000)
.....
#define CHECK_BIT(data, pos)  (data & pos)

if(CHECK_BIT(data, BIT1))
{
..
}

For me personally, I like to show the significance of the bit, for example: 

#define POWER_ON_BIT 0x01 /* bit 1 */
#define RADIO_OFF_BIT 0x02 /* bit 2 */

if( data & RADIO_OFF_BIT)
{
   TurnRadioOn();
}
 
Last edited:

joeyd999

Joined Jun 6, 2011
6,204
Hi guys

I usually check a bit like this:
Code:
#define CHECK_BIT(data, pos)  ((var) & (1<<(pos)))

if (CHECK_BIT(data, 1){
  // do stuff
}

if (CHECK_BIT(data, 2){
  // do stuff
}

../
Is there a way to do something like that to make it look better??
Code:
switch(data){
  case bit_1:
    break;
  case bit_2:
    break;
....
}
What everyone else said. In addition, I'd like you to recognize that your two code snippets would not be functionally equivalent.

The first would test each bit and execute the appropriate code, regardless of the other bit settings.

The second would only execute the code corresponding to the first set bit, and ignore all the others.

In .asm (PIC), I would do it like this:

Code:
callbs  macro   bit,addr
        btfsc   bit
        rcall   addr
        endm

#define bit0 bitregister,0
#define bit1 bitregister,1
#define bit2 bitregister,2

; ...

        callbs    bit0,probit0
        callbs    bit1,probit1
        callbs    bit2,probit2

; ...

probit0
    ;do stuff
        return

probit1
    ;do stuff
        return

probit2
    ;do stuff
        return
 

dl324

Joined Mar 30, 2015
18,225
Is there a way to do something like that to make it look better??
I read somewhere that the Unix kernel uses bit fields for file permissions operations. It's not more efficient, but it's more readable.

I'd be inclined to use something like this:
Code:
  struct {
    unsigned char bit0 : 1;
    unsigned char bit1 : 1;
    unsigned char bit2 : 1;
    unsigned char bit3 : 1;
    unsigned char bit4 : 1;
    unsigned char bit5 : 1;
    unsigned char bit6 : 1;
    unsigned char bit7 : 1;
  } bits;

  bits.bit7 = 1;

  if (bits.bit0) { printf("bit0 stuff\n"); }
  if (bits.bit1) { printf("bit1 stuff\n"); }
  if (bits.bit2) { printf("bit2 stuff\n"); }
  if (bits.bit3) { printf("bit3 stuff\n"); }
  if (bits.bit4) { printf("bit4 stuff\n"); }
  if (bits.bit5) { printf("bit5 stuff\n"); }
  if (bits.bit6) { printf("bit6 stuff\n"); }
  if (bits.bit7) { printf("bit7 stuff\n"); }
I think it's a more natural way to set and check bits and it looks better.
 

WBahn

Joined Mar 31, 2012
32,711
What everyone else said. In addition, I'd like you to recognize that your two code snippets would not be functionally equivalent.

The first would test each bit and execute the appropriate code, regardless of the other bit settings.

The second would only execute the code corresponding to the first set bit, and ignore all the others.
It's worse than that -- the second (the switch()/case version) will only run when that data value ONLY has exactly ONE bit set.

If two bits are set, then the value will not match ANY of the case labels (unless there is a label that has EXACTLY those two bits set).
 

joeyd999

Joined Jun 6, 2011
6,204
It's worse than that -- the second (the switch()/case version) will only run when that data value ONLY has exactly ONE bit set.
Of course. I was commenting on his thought process and the assumption of equivalency, not the actual code.
 

dl324

Joined Mar 30, 2015
18,225
Thanks guys for all your inputs.
If you wanted to be able to use both methods, you could use a union as I suggested earlier:
Code:
  union {
    unsigned char flags;
    struct {
      unsigned char bit0 : 1;
      unsigned char bit1 : 1;
      unsigned char bit2 : 1;
      unsigned char bit3 : 1;
      unsigned char bit4 : 1;
      unsigned char bit5 : 1;
      unsigned char bit6 : 1;
      unsigned char bit7 : 1;
    } bits;
  } data;

  data.flags = 0;
  //data.bits.bit7 = 1;
  data.flags = 0x80;

  if (data.bits.bit0) { printf("bit0 stuff\n"); }
  if (data.bits.bit1) { printf("bit1 stuff\n"); }
  if (data.bits.bit2) { printf("bit2 stuff\n"); }
  if (data.bits.bit3) { printf("bit3 stuff\n"); }
  if (data.bits.bit4) { printf("bit4 stuff\n"); }
  if (data.bits.bit5) { printf("bit5 stuff\n"); }
  if (data.bits.bit6) { printf("bit6 stuff\n"); }
  if (data.bits.bit7) { printf("bit7 stuff\n"); }
My compiler seems to be initializing the bits struct to zero even though I'm not compiling with debug enabled. Using the union, you can use data.flags to set any combination of bits at the same time.
 

WBahn

Joined Mar 31, 2012
32,711
My compiler seems to be initializing the bits struct to zero even though I'm not compiling with debug enabled. Using the union, you can use data.flags to set any combination of bits at the same time.
General word of caution -- don't rely on what your compiler "seems" to do. Unless it is behavior defined by the language standard, what your compiler does may be very different from what other compilers do or even what the next version of your compiler will do. It's best to not even rely on implementation-defined behavior for similar reasons.
 

dl324

Joined Mar 30, 2015
18,225
General word of caution -- don't rely on what your compiler "seems" to do. Unless it is behavior defined by the language standard, what your compiler does may be very different from what other compilers do or even what the next version of your compiler will do. It's best to not even rely on implementation-defined behavior for similar reasons.
That's one of the reasons for my post. I didn't initialize in the first code fragment and I didn't feel like updating the code block. I showed initialization in the later post.

It should also be noted that bit field assignment order could be compiler and platform dependent; even for the same compiler on different architectures. I determined order experimentally. This is relevant when using a union, as in my example.

K&R said bit fields were only valid for ints, but I determined experimentally that it worked with char in my compiler. The unsigned qualifier is optional in some compilers because signed wouldn't make sense, but I always specify explicitly.
 
Last edited:

BobaMosfet

Joined Jul 1, 2009
2,211
Just adding this for the record. A properly defined and declared variable helps ensure a compiler understands the aggregrate structure and how to address it both in the symbol table, and in the relative addressing developed in the linker.

Most people don't properly define and declare types nowadays because they don't know better. I was there when C was born, and helped many compiler manufacturers debug their compilers. A few simple things to know about aggregate data types that become useful when writing more complex things:

Don't do this:
Code:
struct
{
...
}name;
That is a definition, not a declaration. If you are going to bother to create a variable type, do it properly EVERY TIME.
Code:
typedef struct
{
...
}name;
The symbol table then recognizes it as a valid type and it is not necessary to prepend the symbol name with 'struct' in many places it's used.

Another thing I see, that is misused:
Code:
struct foo
{
...
};
This is not a type, nor is it a declaration. It is an incorrect forward declaration and this label 'foo' should only be used in this way, in that location, for a very specific circumstance and no other like so:
Code:
typedef struct foo
{
...
foo  *previousFoo;
foo  *nextFoo;
foo  myfoostruct;
}finalfoo;
A forward declaration is used when you want a structure to be able to reference its own type before it as a type is defined completely. Very handy for linked lists, queues, and many structures in operating systems.

This may seem nitpicky, and pointless if your code seems to work, but it's not. Doing things the right way makes your code simpler, ensures the code is more portable because you ensure the compiler is being told correctly what you are trying to do, and just makes sense.

And yes, I've written compilers and operating systems where lots and lots of such aggregate data types are used in all manner of ways.
 

WBahn

Joined Mar 31, 2012
32,711
Just adding this for the record. A properly defined and declared variable helps ensure a compiler understands the aggregrate structure and how to address it both in the symbol table, and in the relative addressing developed in the linker.

Most people don't properly define and declare types nowadays because they don't know better. I was there when C was born, and helped many compiler manufacturers debug their compilers. A few simple things to know about aggregate data types that become useful when writing more complex things:
I'd be interested in your take on what I do.

I first create the typedef and then the structure definition.

Code:
typedef struct FOO FOO;

struct FOO
{
   int this;
   double that;   
   FOO * fred;
};
The main reason I do this is so that I can put the typedef in a header file and the structure definition in the corresponding code file. Then the code that uses the structure sees only the typedef and can't dink with the structure directly, but rather must treat it as a black box data object and use functions to work with it (whose prototypes are also in the header file).

Now, one thing I've often wondered is whether that FOO inside the structure definition is from the typedef or from the structure definition. In other words, which is the above equivalent to:

Code:
typedef struct s_FOO FOO;

struct s_FOO
{
   int this;
   double that;   
   FOO * fred;
};
or

Code:
typedef struct s_FOO FOO;

struct s_FOO
{
   int this;
   double that;   
   s_FOO * fred;
};
I supposed I should be able to figure out which it is from the standard, but I've never thought about it when I had both the time and the inclination to explore it.
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
I'm in that category. The extent of my formal training in C is a one week class in 1983 and most of what I know is from independent study.
Lol, I sort of teach myself too. The different is, I took a paper on it, but my lecturer/tutor usually came half hour late, and left half hour early. Our session is usually one hour :)
 

BobaMosfet

Joined Jul 1, 2009
2,211
I'd be interested in your take on what I do.

I first create the typedef and then the structure definition.

Code:
typedef struct FOO FOO;

struct FOO
{
   int this;
   double that;  
   FOO * fred;
};
The main reason I do this is so that I can put the typedef in a header file and the structure definition in the corresponding code file. Then the code that uses the structure sees only the typedef and can't dink with the structure directly, but rather must treat it as a black box data object and use functions to work with it (whose prototypes are also in the header file).

Now, one thing I've often wondered is whether that FOO inside the structure definition is from the typedef or from the structure definition. In other words, which is the above equivalent to:

Code:
typedef struct s_FOO FOO;

struct s_FOO
{
   int this;
   double that;  
   FOO * fred;
};
or

Code:
typedef struct s_FOO FOO;

struct s_FOO
{
   int this;
   double that;  
   s_FOO * fred;
};
I supposed I should be able to figure out which it is from the standard, but I've never thought about it when I had both the time and the inclination to explore it.
My cautionary tail is for people who may not have the experience to step outside the bounds and take on the greater responsibility to what is required syntactically to achieve goals that were outside the realm of thought when the language was introduced. My personal methods for opacity come in two flavors: using void * to reduce the datablock to a blob, or not placing what I don't want someone to have access to in the header file.
 

nsaspook

Joined Aug 27, 2009
16,257
Just adding this for the record. A properly defined and declared variable helps ensure a compiler understands the aggregrate structure and how to address it both in the symbol table, and in the relative addressing developed in the linker.

Most people don't properly define and declare types nowadays because they don't know better. I was there when C was born, and helped many compiler manufacturers debug their compilers. A few simple things to know about aggregate data types that become useful when writing more complex things:
I know you don't want to give the impression that structure 'tags' are improper.

http://ee.hawaii.edu/~tep/EE160/Book/chap12/subsection2.1.1.2.html
Tag names in C

In C, the name s appearing in:

struct s
{
...
};

is a tag.
https://www.embedded.com/electronics-blogs/programming-pointers/4024450/Tag-vs-Type-Names
 

WBahn

Joined Mar 31, 2012
32,711
I first create the typedef and then the structure definition.

Code:
typedef struct FOO FOO;

struct FOO
{
   int this;
   double that;  
   FOO * fred;
};
Now, one thing I've often wondered is whether that FOO inside the structure definition is from the typedef or from the structure definition. In other words, which is the above equivalent to:

Code:
typedef struct s_FOO FOO;

struct s_FOO
{
   int this;
   double that;  
   FOO * fred;
};
or

Code:
typedef struct s_FOO FOO;

struct s_FOO
{
   int this;
   double that;  
   s_FOO * fred;
};
I supposed I should be able to figure out which it is from the standard, but I've never thought about it when I had both the time and the inclination to explore it.
Shortly after posting this I realized that this is one of those things that I've often thought about but that I've already always resolved shortly thereafter -- and then obviously proceeded to forget what I realized shortly after that.

It HAS to be the former case because the latter would require a 'struct' keyword in front of s_FOO within the definition.

Since I always typedef my structures the lack of the 'struct' keyword within the definition looks normal to me and so it takes me a while to realize that it's needed. Of course, if I were to actually code it as written, the compiler would smack me appropriately.
 

bogosort

Joined Sep 24, 2011
696
Another thing I see, that is misused:
Code:
struct foo
{
...
};
This is not a type, nor is it a declaration. It is an incorrect forward declaration. . . . A forward declaration is used when you want a structure to be able to reference its own type before it as a type is defined completely.
In what way is that construct "incorrect"? Forward declarations are a natural and useful aspect of the language.

On the other hand, I consider typedefs generally evil. Their greatest effect is to obscure.
 
Top