■ビット演算と論理演算の違い
#include <stdio.h>
int main(void){
int bit = 0xFF00 & 0xFF; //⇒ 0x00=ゼロ=偽
if(bit) {
printf("真:%x\n",bit);
} else {
printf("偽:%x\n",bit);
}
int log = 0xFF00 && 0xFF; //⇒ 非ゼロ&&非ゼロ=真&&真=真
if(log) {
printf("真:%x\n",log);
} else {
printf("偽:%x\n",log);
}
}
●ビット演算
0xFF00 & 0xFF
↓
0x00
↓
ゼロ
↓
偽
●論理演算
0xFF00 && 0xFF
↓
非ゼロ&&非ゼロ
↓
真&&真
↓
真
●実行結果
./a.out
偽:0
真:1
■短絡評価は、ビット演算無し論理演算有り
#include <stdio.h>
#include <stdbool.h>
bool True(void){
printf("%s⇒",__func__);
return true;
}
bool False(void){
printf("%s⇒",__func__);
return false;
}
int main(void){
if(False() & True()) puts("結果⇒真");
else puts("結果⇒偽");
if(False() && True()) puts("結果⇒真");
else puts("結果⇒偽");
}
●False() & True()
&はビット演算子なので両辺を簡略化すると
0&1=0=偽となり
if(偽)は成立しないのでelse節 が表示される。
●False() && True()
&&は論理演算子なので両辺を簡略化すると
0&&1=ゼロ&&非ゼロ=偽&&真=偽となる。
第一条件が成立しなかった時点で、
この条件式全体が成立しない事が確定するので
第二条件を評価する必要がない
すなわちTrue()関数は呼ばれない。
これを短絡評価(ショートサーキット動作)と
言う。
●実行結果
./a.out
False⇒True⇒結果⇒偽
False⇒結果⇒偽
■Segmentation fault (コアダンプ)するかも
#include <stdio.h>
void bit_and(char *p){
printf("%s⇒",__func__);
if ((p != NULL) & (p[0] != '\0')) //ビット演算子
puts(p) ;
else
puts("nop");
}
void log_and(char *p){
printf("%s⇒",__func__);
if ((p != NULL) && (p[0] != '\0')) //論理演算子
puts(p) ;
else
puts("nop");
}
int main(void){
log_and("ABC");
log_and(NULL);
bit_and("DEF");
bit_and(NULL);
}
論理演算&&を使用すべきところで
ビット演算&を使用して
短絡評価が行われずコアダンプしてしまう例です。
●実行結果
./a.out
log_and⇒ABC
log_and⇒nop
bit_and⇒DEF
Segmentation fault (コアダンプ)
未定義動作なのでコアダンプするとは限りませんが。。。。
■ビット単位のOR演算子【|】と 論理OR演算子【||】の違い
#include <stdio.h>
int main(void){
/*
0xFF00
0x00ff
------
0xFFff
*/
printf("ビット演算 %x\n",0xFF00 | 0xFF);
/*
0xFF00||0xFF
⇒非ゼロ||非ゼロ
⇒真||真
⇒真
⇒1
*/
printf("論理演算 %x\n",0xFF00 || 0xFF);
}
●実行結果
./a.out
ビット演算 ffff
論理演算 1
■短絡評価有無の違い
#include <stdio.h>
#include <stdbool.h>
bool Ltrue(void){
printf("左⇒");
return true ;
}
bool Rfalse(void) {
printf("右⇒");
return false ;
}
int main(void){
//ビット演算
if(Ltrue() | Rfalse()) puts("両辺実行");
else puts("来ない");
//論理演算
if(Ltrue() || Rfalse()) puts("左辺のみ実行");
else puts("来ない");
}
●Ltrue() | Rfalse()
|はビット演算子なので
両辺の関数は必ず呼ばれる(評価される)
1|0=1=真なのでthen節が表示される。
●Ltrue() || Rfalse()
||は論理演算子なのでLtrue()が成立した時点でif文は成立する。
このためRfalse()を呼ぶ必要が無い
(Rfalse()を評価する必要が無い)
●実行結果
./a.out
左⇒右⇒両辺実行
左⇒左辺のみ実行