アサート 解答ページ | Programming Place Plus C言語編 第30章

トップページC言語編第30章

問題①

問題① 標準エラーに、末尾での改行付きで文字列を出力するマクロを、デバッグ作業中にだけ有効になるように作成してください。


標準エラーへの出力には fputs関数や fprintf関数を使えばよいですが、改行が必要であることを考えると、fprintf関数を使った方が書きやすいでしょう(fputs関数でやってみようとすると分かります)。

デバッグ作業中かどうかは、NDEBUG で判定する手もありますが、ここでは DEBUG_MODE という独自のマクロを定義するものとします。

#include <stdio.h>

#define DEBUG_MODE

#ifdef DEBUG_MODE
#define DEBUG_PUTS(str)   fprintf(stderr, "%s\n", str)
#else
#define DEBUG_PUTS(str)
#endif

int main(void)
{
    DEBUG_PUTS("Test Message");
}

実行結果:

Test Message

DEBUG_MODE が定義されていなければ、空のマクロになるように #ifdef を使って切り分けています。

問題②

問題② assertの次のような使い方には問題があります。理由を説明して、正しく修正してください。

int n = -2;
assert(++n >= 0);


assert に与える式は評価されるため、副作用があると、assert が有効なときと無効なときとで、プログラムの実行結果が変わってしまう恐れがあります。

インクリメント演算子は、変数の値を変更してしまうので問題があります。assert が有効なら、変数 n の値は +1 されますが、assert が無効であると、変数 n の値は変化しないまま、後続の処理が続くことになります。

インクリメントは、assert の前で行うように修正します。

int n = -2;
++n;
assert(n >= 0);

問題③

問題③ 以下の中から、コンパイル時アサートで記述できる想定はどれか、すべて選んでください。

  1. short型の大きさが 2バイト以上である
  2. int型と long型の大きさが同じである
  3. 標準入力から入力された整数が 0 でない
  4. const を付加した変数 X の値が 1000以上である
  5. NDEBUGマクロが定義されている


コンパイル時アサートは、コンパイル時に判定を行うので、定数式しか与えられません。つまり、定数式で記述可能かどうかという問題です。

1番は、STATIC_ASSERT(sizeof(short) >= 2); のように記述できます。

2番は、STATIC_ASSERT(sizeof(int) == sizeof(long)); のように記述できます。

3番は記述できません。標準入力から入力を受け取るのは、プログラムを実行してからの話です。STATIC_ASSERT はコンパイル時に判定を行うものなので、記述しようがありません。この用途では assertマクロが使えそうですが、ユーザーがどんな入力を行うかは想定できないことですし、assert ではプログラムの実行自体が異常終了してしまうので、assert を使うのは不適切です。都合の悪い入力は if文で判定し、ユーザーにその入力が受け入れられないものであることを伝えるようにします。

4番は記述できません。const型修飾子を付加した変数は、その値を書き換えられなくなるものの、あくまでも変数であって、定数式の中では使えません。

5番は記述できません。マクロが定義されているかどうかを判定する方法は、プリプロセスの中で機能する #ifdef や #if defined といったものだけです(第23章)。


参考リンク


更新履歴

’2018/6/4 新規作成。



第30章のメインページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る