見出し画像

C言語で Java Silver レベルの問題を作ってみる No.25

 プログラミング言語って、しばらく触れてないと細かな部分を忘れてしまいますよね。また、複数のプログラミング言語を習得している人は、頭がこんがりますね。

 そんな方におススメしたいのが、資格試験の問題を1日5問程度解いていく方法です。毎日のスキマ時間を活用して短時間で知識レベルを維持することが出来ますよ。Javaならば、Silverの問題集が最適です。
 Silverを既に取得している人も、これから取得を目指している人もぜひ試してみてください。

 さて、この記事では、タイトルの通り、C言語をテーマにしています。
問題を毎日5問投稿していきますので、C言語を習得中の方、C言語の知識を維持されたい方は、ぜひご活用ください。


■ プリプロセッサ

□ 1. 次のプログラムをコンパイルし、実行したときの出力結果として、正しいものを選びなさい。(1つ選択)

#include <stdio.h>
#define SQUARE(x) ((x) * (x))

int main() {
    int a = 3;
    printf("%d\n", SQUARE(a));
    return 0;
}

A.     3 と表示される
B.   6 と表示される
C.   9 と表示される  
D.   実行時にエラーが発生する


□ 2. 次の引数ありマクロに関する説明で、正しいものを選びなさい。(1つ選択)

A.  マクロは常に展開されるため、型のチェックが行われる
B.  マクロは引数に関数を渡しても問題ない
C.  マクロの展開時には計算結果がキャッシュされる
D.  マクロには再帰呼び出しの制限がない


3. 次の条件付きコンパイルに関する説明で、正しいものを選びなさい。(1つ選択)

A.    条件付きコンパイルは、実行時に条件を評価する
B. 条件付きコンパイルは、ソースコードの一部をコンパイルから除外することができる
C. 条件付きコンパイルは、変数の値を変更するために使用される
D. 条件付きコンパイルは、エラー処理を行うために必ず必要である


□ 4. 次のプログラムをコンパイルし、実行したときの出力結果として、正しいものを選びなさい。(1つ選択)

#include <stdio.h>
#define DEBUG

int main() {
    #ifdef DEBUG
        printf("Debug mode\n");
    #endif
    return 0;
}

A.    何も表示されない
B. Debug mode と表示される
C. コンパイルエラーが発生する
D.   実行時エラーが発生する


□ 5. 次のプログラムをコンパイルし、実行したときの結果として、正しいものを選びなさい。(1つ選択)

#include <stdio.h>
#define MY_HEADER
#ifndef MY_HEADER
void display() {
    printf("Display function\n");
}
#endif

int main() {
    display();
    return 0;
}

A.   何も表示されない
B.   Display function と表示される
C.   コンパイルエラーが発生する
D.   実行時エラーが発生する


解答

1.C

#define SQUARE(x) ((x) * (x)) は、
引数 x を取るマクロ SQUARE を定義します。このマクロは、x の二乗を計算する式 ((x) * (x)) に展開されます。
int a = 3; では、整数型の変数 a に 3 を代入します。
printf("%d\n", SQUARE(a)); では、SQUARE(a) が評価されます。a は 3 なので、マクロは次のように展開されます:
SQUARE(a) => ((3) * (3)) => 9
printf の引数として 9 が渡されるため、プログラムは 9 を出力します。

2.B

A. 誤り: マクロはプリプロセッサによって展開されるため、型のチェックは行われません。つまり、型安全性がありません。

B. 正しい: マクロは引数として任意の式を受け取りますので、関数を渡すことも可能です。ただし、その場合、意図しない結果が得られることもあるため注意が必要です。

C. 誤り: マクロは毎回展開されるため、計算結果はキャッシュされず、同じ引数で何度も展開されることになります。したがって、計算が重い場合は効率が悪くなることがあります。

D. 誤り: マクロ自体は再帰的に定義できますが、実際には過剰な再帰が発生するとコンパイルエラーが起きることがあります。従って、実質的な制限は存在します。

3.B

A. 誤り。条件付きコンパイルはコンパイル時に条件を評価します。したがって、実行時ではなく、ソースコードがコンパイルされる段階でどの部分を含めるかを決定します。

B. 正しい。条件付きコンパイルを使用すると、特定の条件が満たされている場合にのみ、特定のコードをコンパイルに含めることができます。これにより、デバッグ用のコードや特定のプラットフォーム向けのコードなどを容易に管理できます。

C. 誤り。条件付きコンパイルは、ソースコードの一部をコンパイルするかどうかを決定するものであり、変数の値を変更することはありません。

D. 誤り。条件付きコンパイルはエラー処理のために必ず必要ではありません。エラー処理は通常、実行時に行われます。条件付きコンパイルは、特定の条件に基づいてコードを含めたり除外したりするための手段です。

このため、正しい選択肢はBです。

4.B

プログラムの先頭で、#define DEBUG によって DEBUG マクロが定義されています。
#ifdef DEBUG プリプロセッサディレクティブは、DEBUG が定義されている場合にのみ、その下のコードをコンパイルします。
ここでは、printf("Debug mode\n"); が #ifdef DEBUG に囲まれているため、DEBUG が定義されているときはこの行がコンパイルされます。
プログラムを実行すると、"Debug mode" と表示されます。

5.C

プログラムでは、#define MY_HEADER により MY_HEADER マクロが定義されています。
次に、#ifndef MY_HEADER という記述があります。この記述は MY_HEADER が未定義である場合に、その後のコードをコンパイルするように指示します。
しかし、MY_HEADER はすでに定義されているため、#ifndef MY_HEADER の条件は偽となり、その後の void display() 関数の定義は無視されます。
結果として、main 関数内で display() を呼び出すと、コンパイラは display 関数が定義されていないと判断し、コンパイルエラーが発生します。



本日の学習内容

お疲れ様でした。
継続は力なりです。
明日も頑張りましょう!

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