論理型を使いこなす

メンテナンスしやすいプログラムにするために、変数の「スコープ」を意識するのがいいって説明してもらいましたけど、ほかにも変数の扱いで意識しておくといいことってあるんでしょうか?
そうねぇ……。エラー処理では積極的に論理型を使うようにすることかしら。
論理型って、ブーリアンのことですよね!?
そう。論理型は、意外に使いどころが多い型なのよ。
えー、自分ではあんまり使ったことないかもしれないです。詳しく教えてください!

成功・失敗を返却する

まずは、関数の戻り値に論理型を使うケースについて考えてみましょう。

例えば、以下のような正の整数を返す関数があったとします。

int GetPositiveValue(void);

ただし、この関数はエラーになる場合があります。

もし、エラー時には0以下の値を返すという仕様だったとしたら、呼び出し側は次のようになるでしょう。

  int nValue = GetPositiveValue();
  if (nValue > 0) {
    /* 通常の処理 */
  } else {
    /* エラー処理 */
  }

このようなコーディングをするためには、この関数の仕様をしっかりと頭に入れておかなければなりません。

でも、うっかり忘れてしまうこともあるかもしれませんね。

問題なのは、関数のプロトタイプを見ただけではエラーのことを思い出すのが難しいという点よ。

そこで、関数を次のように改良するとどうでしょうか。

bool GetPositiveValue(int *pValue);

こうすれば、関数を使おうとするたびにbool型の戻り値に気付き、エラー処理のことを思い出せるようになりますね。

ちなみに呼び出し側は次のような感じです。

  int nValue = 0;
  if (GetPositiveValue(&nValue)) {
    /* 通常の処理 */
  } else {
    /* エラー処理 */
  }
なるほど。関数の戻り値を論理型にしておけば、それをそのままエラーの判定に使えるんですね!
そういうこと。直感的に関数の仕様が理解できるから分かりやすいし、エラー処理が漏れてしまうことも防げるのよね。

ブロック内の処理の成功・失敗を覚えておく

処理の成功・失敗を一時的に覚えておきたいときもboolが便利よ。

例えば、次のような場合です。

  bool bSuccess = true;

  for (・・・) {
    /* 何かの処理をして・・・ */

    if (・・・) {
      /* ここで失敗した! */
      bSuccess = false;
      break;
    }
  }

  if (bSuccess) {
    /* 成功時の処理 */
  } else {
    /* 失敗時の処理 */
  }

この方法は手前の処理の成功・失敗によって、次の処理を振り分ける場合に有効です。

そっかぁ。今までも同じようなプログラムは書いていたはずなんですけど、boolを使ったほうがうっかりミスを防げそうですね。
そうなのよ。だから使えそうな場面では、積極的にboolを使うのがおすすめよ。

C言語でブーリアンを使うには?

ちなみに。

C言語でboolを使うには、<stdbool.h>をインクルードする必要があるわよ。
#include <stdbool.h>

ただし、古めのC言語はboolをサポートしていません。

どうしても古い環境でブーリアンを使いたいときは、自分で定義してしまいましょう。

例えば、こう。

#ifndef __cplusplus
  typedef int bool;
  #define true  1
  #define false 0
#endif

または、こんな風にすればいいですね。

#ifndef __cplusplus
  typedef enum {
    false = 0,
    true  = 1
  } bool;
#endif

なお、C++の場合は最初からboolに対応しています。


boolを使うとエラー判定がシンプルに書けるし、あとからプログラムを見直したときも何をやっているかが一目瞭然になりますね。
そう。分かりやすくて必要な処理に集中しやすいプログラムになるから、実装漏れやバグの防止にもつながるわね。
ふむふむ。これからは、論理型の変数を使いこなせるように意識してみます!
ここがポイント!
処理の成功・失敗を判定するケースでは、積極的に論理型の変数を使うようにしましょう。関数の仕様を直感的に理解でき、エラー処理をうっかり忘れるというミスも防げます。