言語としてのCはごく小さなものです - 型、演算子、制御の流れ、関数、ポインタ。表示もできず、ファイルも読めず、文字列の比較もメモリの確保もできません。そのすべてが標準ライブラリであり、適合するすべての処理系が同梱するヘッダーの集まりです。
このページは地図です。各節でそのヘッダーが何のためのものかを述べ、短い動く例を1つ示し、より詳しいページがあればそこを指し示します。
stdio.h - 入出力
ほぼすべてのプログラムで最初にインクルードするヘッダーです。printf と scanf、FILE 型とファイル関連の関数、そしてより安全な行単位の入力関数を持っています。
要点。出力には printf、fprintf、sprintf、snprintf。入力には scanf、fscanf、sscanf、fgets、getchar。ファイルには fopen、fclose、fread、fwrite、fseek。より深い解説は printf、scanf、ファイル操作にあります。
覚えておく価値のある規則が1つ。gets() は決して使わないこと。バッファの大きさを知る手段がなく、C11で標準から削除されました。代わりは fgets(buf, sizeof buf, stdin) です。
stdlib.h - 汎用ユーティリティ
なんでも屋です。メモリ、変換、乱数、プロセス制御、整列。
主なもの。malloc、calloc、realloc、free(動的メモリを参照)。変換には atoi、atof、strtol、strtod - atoi が静かに 0 を返すところで失敗を報告できる strto* 系列を選びましょう。rand と srand(乱数を参照)。exit、abort、getenv、system。そして qsort/bsearch。
string.h - 文字列とメモリブロック
C言語の文字列は '\0' で終わる char の配列であり、それに対するすべての操作は関数呼び出しです。
2つの習慣が、このヘッダーがバッファオーバーフローの源になるのを防ぎます。常に格納先の大きさを把握すること、そして strcmp が等しいときに 0 を返すことを忘れないこと - if (strcmp(a, b)) は文字列が異なるときに真になります。より安全な strncpy/snprintf のパターンは文字列関数で詳しく扱います。
math.h - 数学
sqrt、pow、fabs、floor、ceil、round、fmod、三角関数と対数の系列、INFINITY と NAN。
これはリンカのフラグが必要になりうる唯一のヘッダーです。Linuxではコンパイルコマンドの末尾に -lm を加えないと、リンカが「undefined reference to sqrt」と報告します。詳しい案内は数学関数にあります。
time.h - 時計と日付
struct tm の2つのずれが誰をも捕まえます。tm_year は1900年からの数え、tm_mon は0始まりです。time(NULL) は srand の種としても定番です。
ctype.h - 文字の分類
小さいながら、見た目より役に立ちます。各関数は1文字を取り、はい/いいえの問いに答えるか、大文字小文字を変換します。
一式はこうです。isalpha、isdigit、isalnum、isspace、isupper、islower、ispunct、isxdigit、isprint、それに toupper と tolower。
(unsigned char) のキャストに注目してください。これらの関数は unsigned char として表現できる値と EOF について定義されています。素の char はほとんどのシステムで符号付きなので、127を超えるバイトは負数として届き、呼び出しが未定義動作になります。キャストのコストはゼロで、この種の問題をまるごと取り除いてくれます。
そして手製の判定よりこちらを選びましょう。c >= '0' && c <= '9' はたまたま動きますが、isdigit(c) は意図をそのまま述べており、どこでも正しいままです。
limits.h と float.h - 型の端
このマシンで int はどこまで大きくなれるか? これらのヘッダーがそれに答え、その答えこそ可搬なコードが仮定せずに問い合わせる理由です。
INT_MAX はオーバーフローが起きる前にそれを確認する手段です。符号付きのオーバーフローは、あとから調べられる巻き戻りではなく未定義動作なので、これは重要です。
stdbool.h と stdint.h - よりよい型
CにはC99まで真偽値の型がありませんでした。<stdbool.h> がそれを提供します。
bool、true、false は _Bool、1、0 のマクロですが、意図を明白にしてくれます。(C23ではキーワードになり、このヘッダーはもう必要ありません。)
<stdint.h> は幅が保証された型を与えます - ファイル形式、ネットワークプロトコル、そして「int はたぶん32ビット」では不十分な組み込みのすべてに不可欠です。
<inttypes.h> の PRId32 形式のマクロは、現在のプラットフォームで各固定幅型に対して正しい printf の指定子へ展開されます - %d は int32_t に対してあるシステムでは正しく別のシステムでは誤りなので、これが可搬な表示の方法です。
assert.h - 前提を確認する
assert(expr) は式が真のとき何もせず、偽のときメッセージを出してプログラムを中断します。
-DNDEBUG を付けてコンパイルするとすべてのアサーションが取り除かれるので、リリースビルドでのコストはゼロです。これは同時に警告でもあります。アサートの中に副作用を置いてはいけません。 assert(read_next() > 0) はリリースビルドで読み取りをまるごと止めてしまい、そのバグは本番でしか現れません。
アサーションはあなたの間違いのためのものです - コードが正しければあり得ないはずの条件です。ユーザーの不正な入力はアサーションではありません。それは if とエラーメッセージです。
残りを手短に
<stddef.h>-size_t、ptrdiff_t、NULL、offsetof<stdarg.h>- 可変長引数の関数、printfの裏側の仕組み<errno.h>-errnoと、呼び出しが失敗した理由を報告するperror、strerror<signal.h>- Ctrl-C などのシグナルの処理<setjmp.h>- 非局所的なジャンプ。正解であることは稀<locale.h>、<wchar.h>、<wctype.h>- ロケールとワイド文字<stdnoreturn.h>、<stdalign.h>、<threads.h>、<stdatomic.h>- C11での追加
2つの習慣がこのライブラリを扱いやすくします。シグネチャを推測する前にマニュアルページを読むこと - macOSとLinuxの man 3 strtol は権威があって速いです。そして戻り値を確認すること。malloc、fopen、strtol はどれも失敗を報告しますし、それを無視するプログラムはずっと後に、ずっと不明瞭な形で失敗します。
よくある質問
C言語の標準ライブラリとは何ですか?
適合するすべてのC処理系が提供する関数・型・マクロの集合で、およそ30のヘッダーにまとめられています。入出力(<stdio.h>)、メモリと変換(<stdlib.h>)、文字列(<string.h>)、数学(<math.h>)、時刻、文字の分類、数値型の限界を扱います。Cには組み込みの入出力も文字列処理もありません - そのすべてがここから来ます。
stdio.h と stdlib.h の違いは何ですか?
<stdio.h> は入出力です。printf、scanf、fopen、fgets、FILE。<stdlib.h> は汎用ユーティリティです。malloc と free、atoi と strtol、rand と srand、exit、qsort、bsearch。典型的なプログラムは両方をインクルードします。
ctype.h は何をするものですか?
1文字を分類したり変換したりします。isdigit、isalpha、isalnum、isspace、isupper、islower、ispunct、それに toupper と tolower です。c >= '0' && c <= '9' のような手書きの比較の代わりにこれらを使うほうが明快で、あらゆるロケールと文字集合で正しく動きます。
C言語の標準ライブラリを使うのにリンクが必要ですか?
いいえ、ただし1つ例外があります。数学関数です。標準Cライブラリは自動的にリンクされますが、Linuxでは <math.h> の実装が別のライブラリにあるので、sqrt などにはコンパイルコマンドの末尾に -lm が必要です。それ以外は正しい #include だけで足ります。