ローカル変数ではBOOLではなくbool型を利用する【ライトサイドObjective-C】


Objective-Cのメソッド宣言時や、BOOL型の結果をやり取りする際には当然、従来通りBOOL型を使います。

BOOL yea = [@"foobar" hasPrefix:@"foo"]; // YES

ただし、Objective-Cとはあまり関係のない処理を記述する際や、ローカル変数宣言の際には、無理にBOOL型を使おうとはせずに、C言語由来のより安全なbool型を利用することをオススメします。

bool yap = mask() << 8; // true

と言うのも、C言語には「0はfalseと同等、0以外の値はtrueと同等」という常識がありますが、この常識はBOOL型に対しては通用しない場合があります。

int cond = 256;
BOOL flag_BOOL = (BOOL)cond;
bool flag_bool = (bool)cond;
printf("%s\n", flag_BOOL ? "true" : "false"); // false (?!)
printf("%s\n", flag_bool ? "true" : "false"); // true

BOOLは内部的に符号付きのchar型として定義されているため、char型の有効範囲(-128~127)を超えた値が代入されると整数オーバーフローを引き起こし、代入値によっては値が0と見なされてしまうことがあります。

つまり0以外の値であってもfalseとして見なされてしまう場合がある。

BOOL型でこれらの問題に対処するためには、条件式による厳密な値確定処理や反則的な型変換が必要になる場合があります。

// 問題への対処方法
int cond = 256;
BOOL flag_BOOL = cond ? YES : NO; // YES
BOOL flag_BOOL = (bool)cond;      // YES

if (cond) flag_BOOL = YES; else flag_BOOL = NO;


// 注意:BOOL型の場合、キャストだけでは不十分
BOOL flag_BOOL = (BOOL)cond; // NO

bool型は安全

bool型を使えば上記と同等の対処が自動的に行われるようになります。

bool flag_bool = cond; // true

bool型の多くのケースでは、BOOL型の時のような問題が起こらないことが仕様上保証されています。

演算結果がint型の範囲内に収まる場合は問題ありませんが、それ以外のケース(符号なし整数型のオーバーフロー等)には引き続き注意する必要があります。

BOOL型の問題はビット演算等でもよく陥りがちな問題ですので、注意しましょう。

enum { AutoIndent = 1 << 7, SmartIndent = 1 << 8 };
long flags = AutoIndent | SmartIndent;
{ // BOOL(signed char)版
  BOOL hasAutoIndent  = flags & AutoIndent;
  BOOL hasSmartIndent = flags & SmartIndent;
  printf("%s\n", hasAutoIndent ? "true" : "false");  // true
  printf("%s\n", hasSmartIndent ? "true" : "false"); // false (?!)
}
{ // bool版
  bool hasAutoIndent  = flags & AutoIndent;
  bool hasSmartIndent = flags & SmartIndent;
  printf("%s\n", hasAutoIndent ? "true" : "false");  // true
  printf("%s\n", hasSmartIndent ? "true" : "false"); // true
}

BOOL yes = flags & Mask;のような記述はよくやりがちな問題ですので、同様のコードは見つけ次第bool yes = flags & Mask;に書き換えるとよいかと思います。

演算結果をBOOL型の戻り値として返すようなケースでは、従来通りBOOL型を使うようにしましょう。BOOL yes = (flags & Mask) ? YES : NO;BOOL yes = (flags & Mask) == Mask;と記述するようにすると安全になりますし、「お行儀の良いコード」にもなります。

まとめ

  • Objective-Cは仕様上の注意をよく読み、用法用量を守って正しくお使い下さい。
  • C++は仕様上の注意をよく読み、用法容量を守って正しくお使い下さい。

広告

ローカル変数ではBOOLではなくbool型を利用する【ライトサイドObjective-C】」への1件のフィードバック

  1. ピンバック: ライトサイド Objective-C コーディング規約 | MaryCore

コメントは停止中です。