C言語を学び始めたばかりの方にとって、標準入出力関数の多さは混乱の種になりがちです。
特に、1文字を出力するための関数であるputcharとputcは、名前も機能も非常によく似ているため、「どちらを使えばよいのか」と疑問に思うことも多いでしょう。
この記事では、これら2つの関数の決定的な違いや、内部的な動作の仕組み、そして実際の開発現場での使い分けについて詳しく解説します。
putchar関数の基本と特徴
putcharは、C言語の標準ライブラリであるstdio.hで定義されている、標準出力(stdout)に対して1文字を書き出すための関数です。
putcharの構文
putcharのプロトタイプ宣言は以下のようになっています。
int putchar(int c);
引数として渡すcは、出力したい文字の文字コード(ASCIIコードなど)をint型で指定します。
戻り値は、書き込みに成功した場合は書き込まれた文字を、失敗した場合にはEOFを返します。
putcharの使用例
標準出力、つまり一般的にはコンソール画面に文字を表示するシンプルな例を確認してみましょう。
#include <stdio.h>
int main(void) {
char ch = 'A';
// 標準出力に1文字表示
putchar(ch);
putchar('\n'); // 改行を出力
return 0;
}
A
このように、putcharは出力先が標準出力に固定されているため、非常にシンプルに記述できるのが特徴です。
putc関数の基本と特徴
一方でputcは、出力先のストリームを任意に指定できるという自由度の高い関数です。
putcの構文
putcのプロトタイプ宣言は以下の通りです。
int putc(int c, FILE *stream);
putcharとの最大の違いは、第2引数にFILE構造体へのポインタをとることです。
これにより、画面だけでなく、ファイルやエラー出力など、特定の出力先を選択することが可能になります。
putcの使用例
以下のプログラムは、putcを使用してファイルに文字を書き込む例です。
#include <stdio.h>
int main(void) {
FILE *fp;
fp = fopen("test.txt", "w");
if (fp == NULL) {
return 1;
}
// ファイルに 'B' を書き込む
putc('B', fp);
fclose(fp);
return 0;
}
この例では、putcの第2引数にファイルポインタを指定することで、標準出力ではなくファイルへ書き込みを行っています。
putcとputcharの決定的な違い
これら2つの関数の違いを整理すると、大きく分けて3つのポイントがあります。
1. 出力先の自由度
putcharは出力先が常にstdout(標準出力)に限定されています。
これに対し、putcはstdout、stderr(標準エラー出力)、あるいはユーザーがオープンしたファイルなど、任意の出力ストリームを指定可能です。
実は、C言語の規格上、putchar(c)はputc(c, stdout)と全く同じ動作をすることが保証されています。
つまり、putcharはputcの特定のケースを簡略化したものと言えます。
2. マクロとしての実装
ここが重要なテクニカルポイントですが、putcは多くの処理系においてマクロとして実装されています。これに対し、後述するfputcは常に関数として実装されます。
putcがマクロであることの利点は、関数呼び出しのオーバーヘッドがないため、大量の文字を出力する際に実行速度がわずかに速くなる可能性があることです。
しかし、マクロであるために、第2引数(ストリーム)を評価する際に副作用が発生する可能性があるという注意点もあります。
3. 引数の数
見たままの違いですが、引数の数が異なります。
| 関数名 | 引数の数 | 主な用途 |
|---|---|---|
| putchar | 1つ | 標準出力への手軽な1文字出力 |
| putc | 2つ | ファイル出力やエラー出力を含む汎用的な出力 |
実装の詳細と「fputc」との関係
putcを語る上で欠かせないのが、fputc関数の存在です。
putcとfputcは機能的には同一ですが、以下の点が異なります。
- putc: マクロとして実装されることが多いため、高速だが引数の副作用に注意が必要。
- fputc: 必ず「関数」として実装される。関数ポインタとして扱うことができる。
近代的なコンパイラではその差はごくわずかですが、「マクロとしての評価を避けたい場合や、関数としてアドレスを取得したい場合」にはfputcが選ばれます。
逆に、putcharは内部でputcを呼び出していることが多いため、手軽さと速度のバランスを取った設計になっています。
どちらを使うべきか?使い分けのガイドライン
プログラミングの実践において、どのように使い分けるべきか指針を示します。
putcharを使うべき場面
画面にメッセージを表示する場合や、デバッグ目的で簡単な値をコンソールに出したいときはputcharが最適です。
- 標準出力しか使わないことが確定している。
- コードを短く、読みやすく保ちたい。
putcを使うべき場面
ファイル操作を伴うプログラムや、出力先を切り替える必要があるライブラリを作成する場合はputcを選択します。
- ファイルへの書き込みを行う。
stderrに対してエラーログを出力したい。- ループ内で大量の文字を処理し、極限までパフォーマンスを追求したい。
注意点:引数の副作用
putcを使用する際、以下のような記述は避けるべきです。
// 非推奨な例
putc('A', fp++);
putcがマクロで実装されている場合、fp++が複数回評価されてしまう危険性があります。
ストリーム引数には、常に安定した変数を渡すようにしましょう。
まとめ
C言語におけるputcharとputcは、どちらも1文字を出力するための重要な道具です。
- putcharは、標準出力専用のシンプルな関数であり、内部的には
putc(c, stdout)として動作します。 - putcは、出力先を自由に指定できる汎用的なマクロ(または関数)であり、ファイル出力などで威力を発揮します。
基本的な使い分けとしては、コンソール表示ならputchar、それ以外ならputcと覚えておけば間違いありません。
また、より安全性を重視する場合や関数として扱いたい場合にはfputcという選択肢があることも覚えておくと、C言語の理解がさらに深まるでしょう。
これらの関数の特性を正しく理解し、状況に応じて適切なツールを選択できるようになることは、効率的でバグの少ないプログラムを書くための第一歩です。
今後の開発で文字出力を行う際は、この記事で紹介した違いをぜひ思い出してみてください。
