■この記事の概要
この記事では、C言語におけるビット反転(~)と論理反転(!)の違いや、これらの演算子を誤用した場合の問題点について説明しています。
特に、警告メッセージやエラーの原因となる例をコードとともに解説しています。
■【チルダ~】対【ビックリマーク!】
●ビット反転【チルダ~】
1 ⇒~ビット反転 ⇒0xFFFFfffE(2進数1111…0)
0 ⇒~ビット反転 ⇒0xFFFFfffF(2進数1111…1)
●論理反転【ビックリマーク!】
1 (真)⇒!論理反転 ⇒0(偽)
0 (偽)⇒!論理反転 ⇒1(真)
■&&でなくて&でしょう
warning: ‘~’ on a boolean expression
警告:ブール式で’~’チルダが使われた
[-Wbool-operation]
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
void f1(uint32_t x,uint32_t y)
{
uint32_t z;
z = ~(x && y); //NG
printf("%x\n",z);
z = ~(x & y); //OK
printf("%x\n",z);
}
~ビット反転と!論理否定とは違います。
論理式に対して~演算子を使用してビット反転するのは
誤りの可能性があります。
多分
&&ではなくて
& でしょう
■~でなくて!でしょう
void f2(bool x,bool y)
{
bool z;
z = ~(x && y); //NG
printf("%x\n",z);
z = !(x && y); //OK
printf("%x\n",z);
}
論理式に対して~演算子を使用してビット反転するのは
誤りの可能性があります。
多分~ではなくて!でしょう
■bool型変数に~演算子を使うのは間違い
void f3(bool x)
{
//怪しい:bool型のビット反転
printf("%x\n",~x); //NG
//以下のどちらかにしかならない
//->ffffffff
//->fffffffe
printf("%x\n",!x);
}
bool型変数に対して~演算子を使用してビット反転すると
0xffffffff か
0xfffffffe にしかならないので
誤りの可能性があります。
多分~ではなくて!でしょう
■16進数定数に!演算子を使うのは間違い
void f4(void)
{
uint32_t x = !0x2;//NG:16進数を論理反転
printf("%x\n",x);
uint32_t y = ~0x2 ;//OK
printf("%x\n",y);
}
16進数定数を!演算子を使用して論理反転するのは
誤りの可能性があります。
多分!ではなくて~でしょう。
#残念ながらgcc/clangで警告は現状でません。
■is系関数に~チルダを使うのは間違い
#include <stdio.h>
#include <ctype.h>
//X<ctype.h>のis系関数に~チルダを使用
void 間違い(char *string){
for(char *p = string ; *p;p++){
if(~isalpha(*p)){
printf("%s:アルファベットでない %c\n",__func__,*p);
}
}
}
//◎<ctype.h>のis系関数に!ビックリを使用
void 正解(char *string){
for(char *p = string; *p;p++){
if(!isalpha(*p)){
printf("%s:アルファベットでない %c\n",__func__,*p);
}
}
}
int main(void){
static char *string = "abc123def456?#$%&";
間違い(string);
puts("--------");
正解(string);
}
<ctype.h>で提供されているis系関数に対して
ビット演算子の~を使用するのは恐らく間違いでしょう。