見出し画像

C言語教室 第11回 - プリプロセッサとマクロ 答案提出


課題

說明で使った MAX(x,y) というマクロで、引き数にインクリメント演算子を含んだ変数を書くと何が起こるか考察しなさい。

えーっと。
書いたのがこのコード。

#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main()
{
    int a, b;
    int max_ab, max_ab_inc_f, max_ab_inc_b;
    
    a = 537;
    b = 9274;
    max_ab = MAX(a, b);
    printf("max_ab = %d\n", max_ab);
    
    a = 537;
    b = 9274;
    max_ab_inc_f = MAX(++a, ++b);
    printf("max_ab_inc_f = %d\n", max_ab_inc_f);
    
    a = 537;
    b = 9274;
    max_ab_inc_b = MAX(a++, b++);
    printf("max_ab_inc_b = %d\n", max_ab_inc_b);
}

でもって、実行結果的がこれ。

max_ab = 9274
max_ab_inc_f = 9276 
max_ab_inc_b = 9275

面白いっちゃあ、面白いんだけど。
一行に複数の演算子が入ってるのが、めっぽう苦手だったりする。。。
考察については後述。


演習

プリプロセッサが自分の書いたコードを、どのように展開しているのかを確認する方法を調べなさい。

私の場合は「-E」オプションをつけてコンパイルしました。
-E」オプションは、
プリプロセッサだけを実行する
というオプション。
これで実行すればプリプロセッサが展開したコードが出力されます。結果、プリプロセッサがどう展開するのかが一目瞭然となるわけです。

ちなみに先のコードを「-E」オプションをつけてコンパイルすると次のようになります。

最初に「<stdio.h>」が展開されるのですが、これはあまりに大きいのでカット。今回必要だった「printf」のプロトタイプ宣言だけ展開しておきます。

<前略>

int printf(const char* __fmt, ...) __attribute__((__format__(printf, 1, 2)));                                               

<中略>

int main()
{
    int a, b;
    int max_ab, max_ab_inc_f, max_ab_inc_b;
    a = 537;
    b = 9274;
    max_ab = ((a) > (b) ? (a) : (b));
    printf("max_ab = %d\n", max_ab);
    
    a = 537;
    b = 9274;
    max_ab_inc_f = ((++a) > (++b) ? (++a) : (++b));
    printf("max_ab_inc_f = %d\n", max_ab_inc_f);
    
    a = 537;
    b = 9274;
    max_ab_inc_b = ((a++) > (b++) ? (a++) : (b++));
    printf("max_ab_inc_b = %d\n", max_ab_inc_b);
}

「MAX」は三項演算子に展開されています。

(1) max_ab = ((a) > (b) ? (a) : (b));
(2) max_ab_inc_f = ((++a) > (++b) ? (++a) : (++b));
(3) max_ab_inc_b = ((a++) > (b++) ? (a++) : (b++));

下の2つは結果が違います。

(2)は、
  (a)++a
  (b)++b
  (c)a と b を比較
  (d)++b
  (e)max_ab_inc_f に b を代入

(b)と(d)で2回インクリメントされた結果が「max_ab_inc_f」に代入されます。

(3)は、
  (a)a と b を比較
  (b)a++
  (c)b++
  (d)max_ab_inc_f に b を代入
  (e)b++

(b)でインクリメントされた結果だけが「max_ab_inc_f」に代入されます。

「++a」と「a++」で結果が異なるので要注意です。

for 文も

for (i = 0; i < 10; i++)

でなくて

for (i = 0; i < 10; ++i)

とすべきというのを、どこかで読んだような。
どう違うんだったかは・・・まぁ、忘れた(~_~;)。
どなたかご存知だったら教えて。


この記事が気に入ったらサポートをしてみませんか?