Menu

C言語の標準ライブラリ:知っておく価値のあるヘッダーの地図

各標準ヘッダーが何を与えてくれるか - stdio.h、stdlib.h、string.h、math.h、time.h、ctype.h、limits.h、stdbool.h、stdint.h、assert.h - をそれぞれ短い動く例とともに。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

言語としてのCはごく小さなものです - 型、演算子、制御の流れ、関数、ポインタ。表示もできず、ファイルも読めず、文字列の比較もメモリの確保もできません。そのすべてが標準ライブラリであり、適合するすべての処理系が同梱するヘッダーの集まりです。

このページは地図です。各節でそのヘッダーが何のためのものかを述べ、短い動く例を1つ示し、より詳しいページがあればそこを指し示します。

stdio.h - 入出力

ほぼすべてのプログラムで最初にインクルードするヘッダーです。printfscanfFILE 型とファイル関連の関数、そしてより安全な行単位の入力関数を持っています。

要点。出力には printffprintfsprintfsnprintf。入力には scanffscanfsscanffgetsgetchar。ファイルには fopenfclosefreadfwritefseek。より深い解説は printfscanfファイル操作にあります。

覚えておく価値のある規則が1つ。gets() は決して使わないこと。バッファの大きさを知る手段がなく、C11で標準から削除されました。代わりは fgets(buf, sizeof buf, stdin) です。

stdlib.h - 汎用ユーティリティ

なんでも屋です。メモリ、変換、乱数、プロセス制御、整列。

主なもの。malloccallocreallocfree動的メモリを参照)。変換には atoiatofstrtolstrtod - atoi が静かに 0 を返すところで失敗を報告できる strto* 系列を選びましょう。randsrand乱数を参照)。exitabortgetenvsystem。そして qsortbsearch

string.h - 文字列とメモリブロック

C言語の文字列は '\0' で終わる char の配列であり、それに対するすべての操作は関数呼び出しです。

2つの習慣が、このヘッダーがバッファオーバーフローの源になるのを防ぎます。常に格納先の大きさを把握すること、そして strcmp が等しいときに 0 を返すことを忘れないこと - if (strcmp(a, b)) は文字列が異なるときに真になります。より安全な strncpysnprintf のパターンは文字列関数で詳しく扱います。

math.h - 数学

sqrtpowfabsfloorceilroundfmod、三角関数と対数の系列、INFINITYNAN

これはリンカのフラグが必要になりうる唯一のヘッダーです。Linuxではコンパイルコマンドの末尾に -lm を加えないと、リンカが「undefined reference to sqrt」と報告します。詳しい案内は数学関数にあります。

time.h - 時計と日付

struct tm の2つのずれが誰をも捕まえます。tm_year は1900年からの数え、tm_mon は0始まりです。time(NULL)srand の種としても定番です。

ctype.h - 文字の分類

小さいながら、見た目より役に立ちます。各関数は1文字を取り、はい/いいえの問いに答えるか、大文字小文字を変換します。

一式はこうです。isalphaisdigitisalnumisspaceisupperislowerispunctisxdigitisprint、それに touppertolower

(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> がそれを提供します。

booltruefalse_Bool10 のマクロですが、意図を明白にしてくれます。(C23ではキーワードになり、このヘッダーはもう必要ありません。)

<stdint.h> は幅が保証された型を与えます - ファイル形式、ネットワークプロトコル、そして「int はたぶん32ビット」では不十分な組み込みのすべてに不可欠です。

<inttypes.h>PRId32 形式のマクロは、現在のプラットフォームで各固定幅型に対して正しい printf の指定子へ展開されます - %dint32_t に対してあるシステムでは正しく別のシステムでは誤りなので、これが可搬な表示の方法です。

assert.h - 前提を確認する

assert(expr) は式が真のとき何もせず、偽のときメッセージを出してプログラムを中断します。

-DNDEBUG を付けてコンパイルするとすべてのアサーションが取り除かれるので、リリースビルドでのコストはゼロです。これは同時に警告でもあります。アサートの中に副作用を置いてはいけません。 assert(read_next() > 0) はリリースビルドで読み取りをまるごと止めてしまい、そのバグは本番でしか現れません。

アサーションはあなたの間違いのためのものです - コードが正しければあり得ないはずの条件です。ユーザーの不正な入力はアサーションではありません。それは if とエラーメッセージです。

残りを手短に

  • <stddef.h> - size_tptrdiff_tNULLoffsetof
  • <stdarg.h> - 可変長引数の関数、printf の裏側の仕組み
  • <errno.h> - errno と、呼び出しが失敗した理由を報告する perrorstrerror
  • <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 は権威があって速いです。そして戻り値を確認すること。mallocfopenstrtol はどれも失敗を報告しますし、それを無視するプログラムはずっと後に、ずっと不明瞭な形で失敗します。

よくある質問

C言語の標準ライブラリとは何ですか?

適合するすべてのC処理系が提供する関数・型・マクロの集合で、およそ30のヘッダーにまとめられています。入出力(<stdio.h>)、メモリと変換(<stdlib.h>)、文字列(<string.h>)、数学(<math.h>)、時刻、文字の分類、数値型の限界を扱います。Cには組み込みの入出力も文字列処理もありません - そのすべてがここから来ます。

stdio.h と stdlib.h の違いは何ですか?

<stdio.h> は入出力です。printfscanffopenfgetsFILE<stdlib.h> は汎用ユーティリティです。mallocfreeatoistrtolrandsrandexitqsortbsearch。典型的なプログラムは両方をインクルードします。

ctype.h は何をするものですか?

1文字を分類したり変換したりします。isdigitisalphaisalnumisspaceisupperislowerispunct、それに touppertolower です。c >= '0' && c <= '9' のような手書きの比較の代わりにこれらを使うほうが明快で、あらゆるロケールと文字集合で正しく動きます。

C言語の標準ライブラリを使うのにリンクが必要ですか?

いいえ、ただし1つ例外があります。数学関数です。標準Cライブラリは自動的にリンクされますが、Linuxでは <math.h> の実装が別のライブラリにあるので、sqrt などにはコンパイルコマンドの末尾に -lm が必要です。それ以外は正しい #include だけで足ります。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める