【C言語】
ビット演算子の優先順位は直感と違うif(x&2==2)

誤り:if(x & 2 == 2) ビット演算子  正解:if((x & 2) == 2)

warning: suggest parentheses around comparison in operand of ‘&’

警告:if(x & 2 == 2)はバグ
[-Wparentheses]


■ビット演算子がラッキーで動いている例

#include    <stdio.h>
void f1(int x)
{
    if(x & 1 == 1){ //ラッキー
        printf("成立\n");
    }else{
        printf("不成立\n");
    }
}

if(x & 1 == 1){  //コンパイラはこう解釈する

if(x & (1 == 1)){ // &より==のほうが結合力が強い

if(x & (真)){   // (1==1)は真

if(x & (1)){   //真は1

if(x & 1){

上記のようにコンパイラは解釈するので
結果としてプログラマの意図したとおり動きます。


■if(x & 2 == 2)はバグ

void f2(int x)
{
    if(x & 2 == 2){//★ダメ
        printf("成立\n");
    }else{
        printf("不成立\n");
    }
}

しかしif(x & 2 == 2){は
プログラマの意図したとおりには動きません。

if(x & 2 == 2){をコンパイラはこう解釈する

if(x & (2 == 2)){ // &より==のほうが結合力が強い

if(x & (真)){   // (2==2)は真

if(x & (1)){   //真は1

if(x & 1){
と解釈するので結果としてプログラマの意図したとおり動きません。

※2bit目を確認したかったのに1bit目を確認しています。


■カッコで結合力を明確にした修正例

void f3(int x)
{
    if((x & 2) == 2){//OK!
        printf("成立\n");
    }else{
        printf("不成立\n");
    }
}

&、|、^ビット演算子の結合力は直観と異なります
【演算子の優先度と結合規則】の表を暗記しなくてもよいので
ビット演算子の回りに丸カッコを付ける習慣をつけましょう


参考:

EXP00-C. 括弧を使用して演算の優先順位を指定する

https://www.jpcert.or.jp/sc-rules/c-exp00-c.html