画面に文字を出力 ~ 標準出力と標準エラーへの出力

ここでは、簡単な C 言語のプログラムを作成して、文字を出力してみましょう。

次の内容を foo.c という名前のファイルに保存してください。

#include <stdio.h>

int main() {
  printf("Hello!\n");
  return 0;
}

ソースコードの内容を簡単に説明します。

#include <stdio.h>

あとで printf という関数を使うので stdio.h というヘッダーファイルをインクルードしています。

int main() {

C 言語のプログラムは main という名前の関数から実行されますので、main という名前の関数を用意します。戻り値は int 型にしておきます。

  printf("Hello!\n");

printf 関数は「標準出力」に文字を出力します。ここでは Hello! という文字を出力します。

このプログラムはコマンドラインから実行されますが、「標準出力」というのはこの場合、コマンドラインの画面のことです。

  return 0;

最後に main 関数を終わるときに、正常終了を表す 0return で返します。

Linux では次のようにコンパイルして実行できます。

gcc -o foo foo.c
./foo
Hello!

Windows でも同様です。コンパイラは cl です。

cl foo.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.10.25019 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

foo.c
Microsoft (R) Incremental Linker Version 14.10.25019.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:foo.exe
foo.obj
foo
Hello!

Visual Studio を使うときのコマンドラインからのビルド方法については 「Visual Studio デベロッパーコマンドプロンプトを使った C/C++ プログラムの構築」 をみてください。

さて、プログラムをしっかりみてきましたが、ポイントは printf を呼ぶと 「標準出力」に出力するということです。

標準出力というのは UNIX/Linux 系ではファイルデスクリプタ 1 と決まってます。しかし、Windows ではファイルハンドル 1 などとは決まっていません。 「標準出力に出力する」ということだけです。

標準エラーに出力する

エラーメッセージを出力する場合は通常、正常の出力と区別するために「標準エラー」に出力します。

コマンドラインから実行すると、通常標準出力も標準エラーもどちらもスクリーンに表示されることには代わりありませんので、 一見「どっちでも同じじゃないの?」と思ってしまいます。しかし、実際は出力されているファイルハンドル (ファイルデスクリプタ) は異なります。

標準エラーに出力するには、明示的に fprintf 関数を使って stderr に出力します。

fprintf は第一引数に、ストリームを識別するファイルポインタを受け取り、そのストリームにフォーマットされた文字列を出力します。

#include <stdio.h>

int main() {
  fprintf(stderr, "Hello, stderr!\n");
  return 0;
}
gcc foo.c
./a.out
Hello, stderr!

見ただけでは標準出力と区別できないので、パイプを通して確認してみましょう。

パイプやリダイレクトに関しては「リダイレクトの基本」をみてください。

上の a.out の出力をそのまま tr コマンドに送ろうとしてもうまくいきません。大文字に変換されていません。

./a.out | tr 'a-z' 'A-Z'
Hello, stderr!

標準エラーのファイルデスクリプタ 2 を指定して標準出力 &1 にリダイレクトして、それからパイプに送ると、 次のように確かに tr コマンドが受け取れるので大文字に変換されました。

./a.out 2>&1 | tr 'a-z' 'A-Z'
HELLO, STDERR!

以上、標準出力と標準エラーに出力する方法と、それらの違いについて動作を確認しながら説明しました。