| C標準ライブラリ(libc) |
|---|
| 一般的なトピック |
| その他のヘッダー |
C標準ライブラリは、 libcと呼ばれることもあり、[ 1 ] ISO C標準で規定されているCプログラミング言語の標準ライブラリです。 [ 2 ]オリジナルのANSI C標準から始まり、そのスーパーセットであるC POSIXライブラリと同時に開発されました。 [ 3 ] ANSI Cは国際標準化機構によって採用されたため、[ 4 ] C標準ライブラリはISO Cライブラリとも呼ばれます。[ 5 ]
C 標準ライブラリは、文字列操作、数学的計算、入出力処理、メモリ管理、入出力などのタスク用のマクロ、型定義、関数を提供します。
C標準ライブラリのアプリケーションプログラミングインターフェース(API)は、複数のヘッダーファイルで宣言されています。各ヘッダーファイルには、1つ以上の関数宣言、データ型定義、およびマクロが含まれています
長い安定期間の後、1995 年に批准された C 標準の追加である規範補遺 1<iso646.h> (NA1) で、3 つの新しいヘッダー ファイル ( 、、、、、、 )が追加されました。1999<wchar.h>年に発行された C 標準の改訂版であるC99でさらに 6 つのヘッダー ファイル ( 、、、、、、、)が追加され、2011 年のC11でさらに 5 つのファイル ( 、、、、、、、)が追加され、2023 年のC23でさらに 1 つのファイル ( ) が追加されました。合計で、現在 30 個のヘッダー ファイルがあります。 <wctype.h><complex.h><fenv.h><inttypes.h><stdbool.h><stdint.h><tgmath.h><stdalign.h><stdatomic.h><stdnoreturn.h><threads.h><uchar.h><stdbit.h>
| 名前 | から | 説明 |
|---|---|---|
<assert.h> | プログラムの デバッグ中に論理エラーやその他の種類のバグを検出するのに役立つアサートマクロを宣言します | |
<complex.h> | C99 | 複素数を操作するための関数の集合を定義します |
<ctype.h> | 文字を種類別に分類したり、使用されている文字セット(通常はASCIIまたはその拡張機能の 1 つですが、EBCDICを利用した実装も知られています)に依存しない方法で大文字と小文字を変換するために使用される関数のセットを定義します。 | |
<errno.h> | ライブラリ関数によって報告されたエラー コードをテストします。 | |
<fenv.h> | C99 | 浮動小数点環境 を制御するための関数のセットを定義します |
<float.h> | 浮動小数点ライブラリの実装固有のプロパティを指定する マクロ定数を定義します。 | |
<inttypes.h> | C99 | 正確な幅の整数型を定義します。 |
<iso646.h> | NA1 | 複数の標準トークンを表現するための代替方法を実装するいくつかのマクロを定義します。ISO 646異形文字セット でのプログラミング用です |
<limits.h> | 整数型の実装固有のプロパティを指定する マクロ定数を定義します。 | |
<locale.h> | ローカリゼーション関数を定義します。 | |
<math.h> | 一般的な数学関数を定義します。 | |
<setjmp.h> | 非ローカル終了に使用される マクロsetjmpおよびを宣言します。longjmp | |
<signal.h> | シグナル処理関数を定義します。 | |
<stdalign.h> | C11 | オブジェクトの 配置を問い合わせ、指定します |
<stdarg.h> | 関数に渡されるさまざまな数の引数にアクセスします。 | |
<stdatomic.h> | C11 | スレッド間で共有されるデータに対する アトミック操作用。 |
<stdbit.h> | C23 | バイト順序とビット表現用。 |
<stdbool.h> | C99 | ブールデータ型を定義します。これは、C23のboolコア言語機能となる ため、プレースホルダとして使用されています |
<stdcountof.h> | C2Y | を使用して配列の長さを取得しますcountof()。 |
<stddef.h> | いくつかの便利な型とマクロを 定義します | |
<stdint.h> | C99 | 正確な幅の整数型を定義します。 |
<stdio.h> | コアの入力関数と出力関数を定義する | |
<stdlib.h> | 数値変換関数、疑似乱数生成関数、メモリ割り当て、プロセス制御関数を定義します。 | |
<stdnoreturn.h> | C11 | 戻り値のない関数を指定する場合 |
<string.h> | 文字列処理関数を定義する | |
<tgmath.h> | C99 | 型汎用の数学関数を定義します。 |
<threads.h> | C11 | 複数のスレッド、ミューテックス、条件変数を管理するための関数を定義します。 |
<time.h> | 日付と時刻の処理関数を定義します | |
<uchar.h> | C11 | Unicode文字を 操作するための型と関数 |
<wchar.h> | NA1 | ワイド文字列処理関数を定義する |
<wctype.h> | NA1 | ワイド文字をその種類によって分類したり、大文字と小文字を変換するために使用される 関数のセットを定義します。 |
ヘッダー ファイルのうち 3 つ ( <complex.h>、、<stdatomic.h>および<threads.h>) は、実装でサポートする必要のない条件付き機能です。
POSIX標準では、Unix固有の機能のためにいくつかの非標準Cヘッダーが追加されました。その多くは他のアーキテクチャにも導入されています。例としては、やが挙げられます。他にも多くのグループが非標準ヘッダーを使用しています。GNU Cライブラリには、関数があります。OpenVMSには関数があります。 <fcntl.h><unistd.h><alloca.h>va_count()
Unix系システムでは、APIの正式なドキュメントはmanページの形式で提供されます。ほとんどのシステムでは、標準ライブラリ関数のmanページはセクション3にあります。セクション7には、基礎となる概念に関するより一般的なページが含まれている場合があります(例man 7 math_error:Linux)。
Unix系システムは通常、共有ライブラリ形式のCライブラリを持っていますが、ヘッダーファイル(およびコンパイラツールチェーン)がインストールに存在しない場合があり、C開発が不可能な場合があります。CライブラリはUnix系システムではオペレーティングシステムの一部と見なされます。C標準で指定された関数に加えて、POSIX標準で指定された関数など、オペレーティングシステムAPIの一部である他の関数も含まれています。ISO C標準のものを含むCライブラリ関数は、プログラムで広く使用されており、C言語の実装であるだけでなく、オペレーティングシステムインターフェースの事実上の一部であるかのように扱われています。Unix系オペレーティングシステムは、Cライブラリが削除されると、一般的に機能しなくなります。これは、静的ではなく動的にリンクされたアプリケーションに当てはまります。さらに、カーネル自体(少なくともLinuxの場合)は、どのライブラリからも独立して動作します
Microsoft Windowsでは、コアシステム動的ライブラリ(DLL )がMicrosoft Visual C++コンパイラv6.0用のC標準ライブラリの実装を提供します。Microsoft Visual C++コンパイラの新しいバージョン用のC標準ライブラリは、各コンパイラによって個別に提供されるほか、再頒布可能なパッケージとしても提供されます。Cで記述されたコンパイル済みアプリケーションは、対象システム上に存在することを前提とするのではなく、Cライブラリに静的にリンクされるか、アプリケーションに同梱されているライブラリの動的バージョンにリンクされます。コンパイラのCライブラリ内の関数は、Microsoft Windowsへのインターフェイスとはみなされません。
様々なオペレーティングシステムとCコンパイラには、多くのCライブラリ実装が提供されています。人気のある実装には、以下のようなものがあります。
一部のコンパイラ(例えばGCC [ 8 ])は、C標準ライブラリの多くの関数の組み込みバージョンを提供しています。つまり、関数の実装はコンパイルされたオブジェクトファイルに書き込まれ、プログラムはCライブラリの共有オブジェクトファイル内の関数ではなく、組み込みバージョンを呼び出します。これにより、特に関数呼び出しがインラインバリアントに置き換えられた場合に関数呼び出しのオーバーヘッドが削減され、他の形式の最適化が可能になります(コンパイラは組み込みバリアントの制御フロー特性を認識しているため)。ただし、デバッグ時に混乱が生じる可能性があります(例えば、組み込みバージョンをインストルメントされたバリアントに置き換えることはできません)。
ただし、組み込み関数はISO Cに準拠した通常の関数と同様に動作する必要があります。主な意味は、プログラムがこれらの関数のアドレスを取得してポインタを作成し、そのポインタを介して関数を呼び出すことができる必要があるということです。プログラム内の異なる翻訳単位から同じ関数への2つのポインタが導出された場合、これらの2つのポインタは等しくなければなりません。つまり、アドレスは外部(プログラム全体)リンケージを持つ関数の名前を解決することで得られます。
FreeBSD [ 9 ]および glibc [ 10 ]では、などの一部の関数はsin()デフォルトではリンクされず、代わりに数学ライブラリlibmにバンドルされています。これらのいずれかを使用する場合は、リンカーにディレクティブ を指定する必要があります-lm。POSIXでは、c99コンパイラが をサポートし、ヘッダー、、-lmおよび で宣言された関数が が指定されている場合はリンクに使用できることを要求していますが、関数がデフォルトでリンクされるかどうかは指定していません。[ 11 ] muslは、すべてを単一のlibcライブラリにまとめ、空のlibmを提供することで、この要件を満たしています。[ 12 ]<math.h><complex.h><fenv.h>-lm
C標準によれば、実装がホストされている場合、マクロは__STDC_HOSTED__と定義されなければなりません。ホストされた実装は、C標準で指定されたすべてのヘッダーを持ちます。実装は、これらのヘッダーが存在しないことを意味する、フリースタンディングである場合もあります。 実装がフリースタンディングである場合、 と定義されなければなりません1__STDC_HOSTED__0
C標準ライブラリの一部の関数は、バッファオーバーフローの脆弱性があり、採用されて以来、バグの多いプログラミングを助長することで悪名高い。[ 13 ] [ a ]最も批判されている項目は次のとおりです
strcpy()およびを含む文字列操作ルーチンでは、境界チェックstrcat()が不足しており、境界を手動でチェックしないとバッファ オーバーフローが発生する可能性があります。printf()書式文字列が引数と一致しない場合に実行スタックを破壊しようとする一連のルーチン。この根本的な欠陥から、書式文字列攻撃と呼ばれる一連の攻撃が生まれました。gets()およびscanf()I/O ルーチンのファミリでは、入力長のチェックが (まったくまたは簡単に) 行われないことがあります。のような極端なケースを除きgets()、メモリ管理、境界チェック、入力チェックなどを実行する補助コードを導入することで、すべてのセキュリティ脆弱性を回避できます。これは、標準ライブラリ関数をより安全で使いやすくするラッパーの形で行われることがよくあります。これは、 B. KernighanとR. Pikeによる著書『The Practice of Programming 』にまで遡ります。そこでは、エラーが発生した場合にエラーメッセージを出力してプログラムを終了するラッパーが一般的に使用されていました。
ISO C委員会は技術報告書TR 24731-1 [ 14 ]を発行し、境界チェックと自動バッファ割り当てを備えたいくつかの関数の採用を提案するTR 24731-2 [ 15 ]に取り組んでいます。前者は厳しい批判を受けていますが、一部は称賛されています[ 16 ] [ 17 ]。後者は賛否両論です。
懸念にもかかわらず、TR 24731-1 は ISO/IEC 9899:2011 (C11) の Annex K (境界チェック インターフェイス)の C 標準トラックに統合され、Win32 および Win64 プラットフォーム用の Microsoft の C/++ ランタイム (CRT) ライブラリにほぼ実装されました。
(デフォルトでは、Microsoft Visual StudioのCおよびC++コンパイラは、古い「安全でない」関数を使用すると警告を発します。しかし、MicrosoftのTR 24731-1の実装は、TR 24731-1とAnnex Kの両方と微妙に互換性がないため、[ 18 ] 、移植性の高いプロジェクトではこれらの警告を無効にしたり無視したりすることが一般的です。これらの警告は、
#pragma warning(disable : 4996)問題の呼び出し箇所の前または周囲、または間接的に以下を発行することで
#define _CRT_SECURE_NO_WARNINGS 1ヘッダーをインクルードする前に。[ 19 ]コマンドラインオプションは/D_CRT_NO_SECURE_WARNINGS=1これと同じ効果を持つはず#defineです
このstrerror()ルーチンはスレッドセーフではない、あるいは競合状態に脆弱であるという批判を受けています。
C標準ライブラリの関数のエラー処理は一貫性がなく、混乱を招くことがあります。Linuxのマニュアルページによるとmath_error、「現在の(バージョン2.8)glibcの状況は複雑です。ほとんどの関数(すべてではありませんが)はエラー時に例外を発生させます。一部の関数はerrnoも設定します。いくつかの関数はerrnoを設定しますが、例外を発生させません。どちらも行わない関数もごくわずかです。」[ 20 ]
オリジナルのC言語は、COBOLやFortranなどの従来の言語とは異なり、I/O操作などの組み込み関数を提供していませんでした。時を経て、Cのユーザーコミュニティはアイデアや実装を共有し、現在ではC標準ライブラリと呼ばれています。これらのアイデアの多くは、最終的に標準化されたC言語の定義に組み込まれました。
UnixとCはどちらも、 1960年代後半から1970年代初頭にかけてAT&Tのベル研究所で開発されました。1970年代にはC言語の人気が高まり、多くの大学や組織がそれぞれのプロジェクト向けに独自のC言語を開発し始めました。1980年代初頭には、様々なC言語実装間の互換性の問題が顕在化しました。1983年、米国規格協会(ANSI)は「 ANSI C 」として知られるC言語の標準仕様を策定するための委員会を設立しました。この作業は、1989年にいわゆるC89標準の策定に結実しました。この標準規格の一部には、ANSI C標準ライブラリと呼ばれる一連のソフトウェアライブラリが含まれていました。
POSIXとSUSは、基本的なC標準ライブラリのルーチンに加えて、利用できるべき多くのルーチンを規定しています。POSIX仕様には、マルチスレッド、ネットワーク、正規表現などの用途のためのヘッダーファイルが含まれています。これらは、C標準ライブラリの機能と並行して実装されることが多く、その近似度合いはさまざまです。例えば、glibcはforkwithinなどの関数を実装していますが、 NPTLがlibc.soglibcに統合される前は、独自のリンカーフラグ引数を持つ別のライブラリを構成していました。多くの場合、このPOSIX仕様の機能はライブラリの一部と見なされ、基本CライブラリはANSIまたはISO Cライブラリ として識別される場合があります
BSD libcは、 FreeBSD、NetBSD、OpenBSD、macOSなどのBSDオペレーティングシステムに含まれるCライブラリでサポートされているPOSIX標準ライブラリのスーパーセットです。BSD libcには、元の標準では定義されていない拡張機能がいくつかあり、その多くは1994年の4.4BSDリリース(1989年に最初の標準が発行されてから大幅に開発された最初のバージョン)で初めて登場しました。BSD libcの拡張機能の一部は次のとおりです
<sys/tree.h>–赤黒木とスプレー木 の実装を含む[ 21 ] [ 22 ]<sys/queue.h>–リンクリスト、キュー、テールキューなど の実装[ 23 ] [ 24 ]fgetln() – で定義されています<stdio.h>。これを使ってファイルを1行ずつ読み込むことができます。[ 25 ] [ 26 ] [ 27 ]<fts.h> – ファイル階層を走査するためのいくつかの関数が含まれています[ 28 ] [ 29 ]<db.h>– Berkeley DB に接続するためのいくつかの関数[ 30 ] [ 31 ]strlcat()およびstrlcpy() –strncat()およびの安全な代替手段strncpy()[ 32 ] [ 33 ] [ 34 ] [ 35 ] [ 36 ]<err.h> – フォーマットされたエラーメッセージを印刷するためのいくつかの関数が含まれています[ 37 ] [ 38 ]<vis.h> –vis()関数が含まれています。この関数は、印刷できない文字を視覚的な形式で表示するために使用されます。[ 39 ] [ 40 ] [ 41 ]一部の言語では、標準Cライブラリの機能を独自のライブラリに組み込んでいます。ライブラリは言語の構造に合わせて調整される場合もありますが、操作意味は同様のままです。
C ++言語は、C固有の仕組みを除き、C標準ライブラリの構成要素の大部分を独自に組み込んでいます。C標準ライブラリの関数は、C++標準ライブラリから2つの方法でエクスポートされます
Cおよび標準以前のC++との後方互換性/相互互換性のため、関数はCのようにC標準ヘッダー名を ing した後、グローバル名前空間(::)でアクセスできます。 [ 42 ]ただし、グローバル名前空間を示すために使用される は、同じシンボル名が定義されている他の名前空間のスコープ内にある場合にのみ必要です。したがって、C++98プログラム#include::
#include <stdio.h>int main ( void ) { return puts ( "Hello, world!" ) == EOF ; }コードが同一のC95プログラムと (明らかに) 同一の動作を示すはずです。
C++98以降、C関数は対応するCヘッダーの代わりにヘッダーをインクルードすることで、名前空間std(例:C printfas C++ std::printf、atoias std::atoi、feofas )でも利用できるようになりました。例えば、はおよび の代わりになります。C ++ヘッダー名には拡張子 がないことに注意してください。std::feof<chdrname><hdrname.h><cstdio><stdio.h><cmath><math.h>.h
したがって、上記の 2 つと同等の (一般的に好ましい) C++≥98 プログラムは次のようになります。
#include <cstdio>int main () { return std :: puts ( "Hello, world" ) == EOF ; }C++20 以降を使用している場合は、を に置き換えることができます(ただし、 は に置き換えることができません。モジュールはなどのマクロをエクスポートしないためです)。 #include<cstdio>import<cstdio>;importstd;EOF
上または中の宣言は 自動的に名前空間を修飾するために発行することができる(本質的にプレフィックスを自動的に適用する)が、文を記述すると、ヘッダーのグローバルスコープで使用される場合、潜在的に望ましくないシンボルでグローバル名前空間を汚染する可能性がある。[ 43 ]usingnamespacestd;mainstdstd::using
C++≥98バージョンのCヘッダーのいくつかは欠落しています。例えば、C≥11<stdnoreturn.h>には<threads.h>C++の対応するものがありません。[ 44 ]
その他のマクロはプレースホルダーに縮小され、例えばC95では( C++20までは)必要なマクロはすべてC++98でキーワードとして表現されます。C言語特有の構文構造は、ヘッダーがサポートされていても、一般的にはサポートされていません。[ 45 ]<ciso646><iso646.h>
いくつかのCヘッダーは主にC++との互換性のために存在し、C++ではほぼ空になる傾向があります。例えば、C99 – 17<stdbool.h>では、
#define bool _Bool #define false 0 #define true 1 #define __bool_true_false_are_defined 1C++98 のbool、false、trueキーワードを C でサポートしているように見せかけるためです。C ++11 では互換性のために<stdbool.h>と が必要ですが、 を定義するだけで済みます。C23では古いキーワードが廃止され、代わりに C++98 と同等の新しい、、キーワードが導入されました。そのため、C≥23 と C++≥11 の/ヘッダーは完全に同等です。(特に、C23では のマクロは必要ありません。) <cstdbool>__bool_true_false_are_defined_Boolboolfalsetrue<stdbool.h>cstdbool>__STDC_VERSION_BOOL_H__<stdbool.h>
Cライブラリ関数へのアクセスは、可能な限り、名前空間::stdとC++98以降のヘッダー名を介して行うことが望ましい。採用を促進するため、C++98ではCのヘッダー名が廃止されているため、C互換ヘッダーを使用すると、特に厳格なC++ 98-20プリプロセッサが何らかの診断メッセージを出力する可能性がある。しかし、 C++23では(異例なことに)これらのヘッダーが廃止されているため、新しいC++実装/モードでは、特に指示がない限りエラーメッセージは出力されないはずである。[ 46 ]<*.h>
C++≥23 標準ライブラリモジュールはstd.compat、すべての C 標準ライブラリ シンボルをグローバル名前空間に配置します (すべての<*.h>ヘッダーをインクルードするのと同様)。一方、stdモジュールは C 標準ライブラリ シンボルを名前空間に残しますstd(C ヘッダーの C++ バージョンをインクルードするのと同様)。
他の言語でも同様のアプローチが採用されており、 C 互換関数/ルーチンを共通の名前空間に配置しています。これにはD、Perl、Rubyなどがあります。
CPythonは、独自の共通ライブラリにいくつかのCライブラリ関数のラッパーを含んでおり、ctypesパッケージを介してC関数と変数へのより直接的なアクセスも許可します。[ 47 ]
より一般的には、Python 2.xでは組み込みのファイルオブジェクトは「Cのstdioパッケージを使用して実装されている」と指定されており[ 48 ]、C標準ライブラリの動作が頻繁に参照されています。利用可能な操作(open、、など)はread、対応するC関数( 、、など)writeと同じ動作をすることが期待されています。 fopenfreadfwrite
ただし、 Python 3の仕様は、 Python 2よりも C 仕様への依存度がかなり低くなっています。
Rustはlibc、さまざまなC標準(およびその他の)ライブラリ関数と型定義を使用できるようにするcrateを提供しています。 [ 49 ]
Zigは利用可能なターゲット用のlibcを搭載しています。[ 50 ]
C標準ライブラリは、他の言語の標準ライブラリと比較すると小規模です。Cライブラリは、数学関数、文字列操作、型変換、ファイルおよびコンソールベースのI/Oといった基本的な機能を提供します。C ++標準テンプレートライブラリのような「コンテナ型/コレクション型」の標準セットは含まれておらず、 Javaや.NET Frameworkが標準で提供する完全なグラフィカルユーザーインターフェース(GUI)ツールキット、ネットワークツール、その他豊富な機能は含まれていません。この小規模な標準ライブラリの主な利点は、ISO C環境の構築が他の言語よりもはるかに容易であり、結果としてCを新しいプラットフォームに移植するのが比較的容易であることです。
gets()、1988年には既に作成されていました単一の
文が、プロジェクト全体の名前空間管理を混乱させる可能性があります。したがって、
ヘッダーファイルには
最上位レベルの [ ] 文を使用しないでください。
using namespace std;using namespace
ファイルオブジェクトはCの
stdio
パッケージを使用して実装されており、組み込み
関数を使用して作成できます。
open()