■この記事の概要
この記事では、C言語でのビット演算子とマスクパターンのよくある誤りを解説しています。
特に、if
文でのビット演算の結果が常に真や偽になるケースを紹介し、その原因を詳しく説明しています。
具体的なコード例も提供され、間違いを理解するための参考になります。
■bitwise comparison always evaluates to true
#include <stdio.h>
void f(unsigned int x){
if((x | 1) == 0) puts("ここには来ない");
else puts("常時偽");
if((x & 0) == 0) puts("常時真");
else puts("ここには来ない");
if((x | 1) != 0) puts("常時真");
else puts("ここには来ない");
if((x & 0) != 0) puts("ここには来ない");
else puts("常時偽");
}
int main(void){
f(0);
f(1);
}
if(x|1)👉必ず真
if(x&0)👉必ず偽
となるのでif文判定に意味がありません。
➡実行結果
./a.out
常時偽
常時真
常時真
常時偽
常時偽
常時真
常時真
常時偽
■ビット演算子とシフト演算子の間違い
#include <stdio.h>
int main(void){
unsigned int bit = 0x80;
puts("間違い1");
for(unsigned int i = 0;i <= 7;i++){
if(bit & (0<<i)){
printf("%ubitが立ってます\n",i);
}
}
puts("間違い2");
for(unsigned int i = 0;i <= 7;i++){
if(bit | (1<<i)){
printf("%ubitが立ってます\n",i);
}
}
puts("正しい");
for(unsigned int i = 0;i <= 7;i++){
if(bit & (1<<i)){
printf("%ubitが立ってます\n",i);
}
}
}
if(bit & (0<<i)){👉必ず偽
if(bit | (1<<i)){👉必ず真
となるのでif文判定に意味がありません。
➡実行結果
./a.out
間違い1
間違い2
0bitが立ってます
1bitが立ってます
2bitが立ってます
3bitが立ってます
4bitが立ってます
5bitが立ってます
6bitが立ってます
7bitが立ってます
正しい
7bitが立ってます
■bitwise comparison always evaluates to false
#include <stdio.h>
#include <stdint.h>
char *f(unsigned short x){
if((x & 2) == 1) return "常に不成立";
if((x & 0b0010U) == 0b0001U) return "常に不成立";
if((x & 0xFF00U) == 0x00FFU) return "常に不成立";
if((x & 0x00FFU) == 0xFF00U) return "常に不成立";
return "必ずここに来る";
}
int main(void){
printf("%s\n",f(0));
printf("%s\n",f(1));
printf("%s\n",f(2));
printf("%s\n",f(0x00FF));
printf("%s\n",f(0xFF00));
printf("%s\n",f(0xFFFF));
}
ビットパターンがあっていないので
if文が成立する事はありません。
■Mismatching bitmasks. Result is always 0
[(style)mismatchingBitAnd]
#include <stdio.h>
typedef unsigned int uint32_t ;
void f(uint32_t y)
{
uint32_t x = y & 0xFFFF0000U;
uint32_t z = x & 0x0000FFFFU ;
printf("%x\n",z);
}
上記のマスクパターンでは
yの値に無関係に
zの値は0になります。
■Boolean expression ‘b’ is used in bitwise operation.
警告:bool変数をビット演算に使用した
[(style)bitwiseOnBoolean]
#include <stdio.h>
#include <stdbool.h>
char *f(bool b){
if(b & 2U)
return "到達不能";
else
return "ビットパターンがマッチする事はない";
}
int main(void){
printf("%s\n",f(0));
printf("%s\n",f(1));
printf("%s\n",f(2));
printf("%s\n",f(3));
}
if(b & 2U)でbool変数は0/1しかとらないので2UとビットANDをとる意味がありません。
■ビット演算の結果をtrueと比較するのは多分間違い
#include <stdio.h>
#include <stdbool.h>
#define BIT7 (1U<<7)
//7bit目が立っているか?を判定する正しい方法は?
int main(void)
{
unsigned char x = BIT7;
if((x & BIT7) == 1) puts("A");
if((x & BIT7) == true) puts("B");
if((x & BIT7) != 0) puts("C");
if((x & BIT7) != false) puts("D");
if((x & BIT7) == BIT7) puts("E");
if(x & BIT7) puts("F");
}
(A)x&BIT7が1になる事はありません。
(B)同上
(C)意図した動きをします
(D)同上
(E)社内規約で推奨する場合があります。
(F)筆者は明解なこの書き方を推奨します。
■アンケート
参考: