0

I created a MACRO to see if a bit is set or not. Code is printing 0 instead of 1.

#define IS_BIT_SET(n,x)   ((n&(1<<x)!=0)?1:0)
int main(){
    printf("%d \n",IS_BIT_SET(8,3));
}
user968000
  • 1,765
  • 3
  • 22
  • 31

2 Answers2

4

The != operator has a higher precedence than &.

So your:

n & (1 << x) != 0

is equivalent to:

n & ((1 << x) != 0)

Which, for any value of x that gives a well-defined result, is equivalent to:

n & 1

Which isn't what you want.

To fix this. replace your define with:

(((n & (1 << x)) != 0) ? 1 : 0)

Also, your arguments should probably be wrapped in parentheses if you plan on using this in a more complex situation:

((((n) & (1 << (x))) != 0) ? 1 : 0)

Instead of using a ternary, you can use the fact that the != yields an int of value 0 or 1:

(((n) & (1 << (x))) != 0)

Alternatively, you can skip the comparison to 0, and cast to bool and back to int:

((int) (bool) ((n) & (1 << (x))))

Or stick with the ternary, dropping the comparison to 0:

(((n) & (1 << (x))) ? 1 : 0)

Which one you choose of these last three is a matter of opinion and preference.

Thomas Jager
  • 4,836
  • 2
  • 16
  • 30
  • Thanks, it works now. Just wanted to understand more why are we adding parentheses around the arguments? – user968000 Jul 19 '19 at 18:03
  • 2
    Please see [C macros and use of arguments in parentheses](https://stackoverflow.com/questions/7186504/c-macros-and-use-of-arguments-in-parentheses). – Weather Vane Jul 19 '19 at 18:08
  • Parentheses will make a difference in a case like this: IS_BIT_SET(8,3) returns 1, while IS_BIT_SET(8,2|1) returns 0. – jmq Jul 19 '19 at 20:26
3

The comparison != has higher precedence than & so it's done first. Your code therefore is doing 8 & ((1 << 3) != 0) which is 8 & 1. You need to add parentheses:

#define IS_BIT_SET(n,x)   (((n & (1 << x)) != 0) ? 1 : 0)

int main(){
    printf("%d \n",IS_BIT_SET(8,3));
}

Now it will be understood as (8 & (1 << 3)) != 0 as you want it to be.

Sami Kuhmonen
  • 30,146
  • 9
  • 61
  • 74