C標準ライブラリ(libcとも呼ばれる) [ 1 ]は、ISO C規格で規定されているCプログラミング言語の標準ライブラリです。[ 2 ]元々はANSI C規格から始まり、その上位互換であるC POSIXライブラリと同時に開発されました。 [ 3 ] ANSI Cが国際標準化機構(ISO)に採用されて以来、[ 4 ] C標準ライブラリはISO Cライブラリとも呼ばれています。[ 5 ]
C標準ライブラリは、文字列操作、数学的計算、入出力処理、メモリ管理、入出力などのタスクのためのマクロ、型定義、関数を提供します。
C標準ライブラリのアプリケーションプログラミングインターフェース(API)は、複数のヘッダーファイルで宣言されています。各ヘッダーファイルには、1つ以上の関数宣言、データ型定義、およびマクロが含まれています。
C言語の標準規格の実装は、ホスト型とスタンドアロン型に分類できます。ホスト型実装は標準規格全体をサポートし、標準規格で指定されているすべてのヘッダーファイルが存在する必要があります。これらは通常、オペレーティングシステム上で動作するプログラム向けの実装です。スタンドアロン型実装は、オペレーティングシステムのバージョンでスタンドアロン型実装に必須と指定されている機能以外に、Cライブラリの言語機能を実装する必要はありません。これらは通常、非常に制限されたオペレーティングシステム上、またはハードウェア上で直接動作するプログラム向けの実装です。
長期間の安定の後、1995年に承認されたC標準への追加である規範的補遺1 (NA1)により、3つの新しいヘッダーファイル( <iso646.h>、、<wchar.h>および)が追加されました。 1999年に発行されたC標準の改訂版であるC99により、さらに6つのヘッダーファイル( 、、、、、および)が追加され、2011年のC11によりさらに5つのファイル( 、、、、および)が追加され、2023年のC23によりさらに2つのファイル(および)が追加されました。合計で、現在31個のヘッダーファイルがあります。<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><stdckdint.h>
凡例: : 非推奨: 削除済み
ヘッダーファイルのうち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には、基盤となる概念に関するより一般的なページが含まれている場合があります(Linuxman 7 math_errorなど)。
Unix系システムは通常、共有ライブラリ形式のCライブラリを備えていますが、インストール時にヘッダーファイル(およびコンパイラツールチェーン)が含まれていない場合があるため、C開発ができない可能性があります。Unix系システムでは、Cライブラリはオペレーティングシステムの一部とみなされます。C標準で規定された関数に加えて、POSIX標準で規定された関数など、オペレーティングシステムAPIの一部である他の関数も含まれます。ISO C標準を含むCライブラリ関数は、プログラムで広く使用されており、C言語の実装であるだけでなく、事実上オペレーティングシステムインターフェースの一部であると見なされています。Cライブラリが削除されると、Unix系オペレーティングシステムは一般的に機能しなくなります。これは、静的リンクではなく動的リンクされたアプリケーションにも当てはまります。さらに、カーネル自体(少なくともLinuxの場合)は、どのライブラリとも独立して動作します。
Microsoft Windows では、Microsoft C ランタイム ライブラリがMicrosoft Visual C++コンパイラ v6.0用の C 標準ライブラリの実装を提供します。それ以降のバージョンの Microsoft Visual C++ コンパイラ用の C 標準ライブラリは、各コンパイラによって個別に提供されるほか、再頒布可能な パッケージとしても提供されます。C で記述されたコンパイル済みアプリケーションは、C ライブラリと静的にリンクされるか、対象システムにライブラリが存在することを前提とするのではなく、アプリケーションに同梱されている動的バージョンのライブラリにリンクされます。コンパイラの C ライブラリ内の関数は、Microsoft Windows へのインターフェイスとはみなされません。Windows システム インターフェイスは、C ランタイム ライブラリとは別のライブラリで提供されます。
C言語の標準ライブラリには多くの実装が存在し、様々なオペレーティングシステムやCコンパイラに付属しています。代表的な実装例をいくつか挙げます。
一部のコンパイラ(例えば、GCC [ 8 ])は、C 標準ライブラリの多くの関数の組み込みバージョンを提供しています。つまり、関数の実装はコンパイル済みオブジェクトファイルに書き込まれ、プログラムは C ライブラリ共有オブジェクトファイル内の関数の代わりに組み込みバージョンを呼び出します。これにより、特に関数呼び出しがインラインバリアントに置き換えられる場合、関数呼び出しのオーバーヘッドが削減され、他の形式の最適化が可能になります(コンパイラは組み込みバリアントの制御フロー特性を知っているため)。ただし、デバッグ時に混乱を招く可能性があります(例えば、組み込みバージョンを計測済みバリアントに置き換えることはできません)。
ただし、組み込み関数はISO C規格に従って通常の関数と同様に動作する必要があります。主な要件は、プログラムがこれらの関数のアドレスを取得してポインタを作成し、そのポインタを使用して関数を呼び出すことができる必要があるということです。プログラム内の異なる翻訳単位で同じ関数へのポインタが2つ生成される場合、これらのポインタは等しくなければなりません。つまり、アドレスは外部(プログラム全体)リンケージを持つ関数の名前を解決することによって取得されます。
FreeBSD [ 9 ]および glibc [ 10 ]では、などの一部の関数はsin()デフォルトではリンクされず、代わりに数学ライブラリlibmにバンドルされています。これらの関数のいずれかを使用する場合は、リンカにディレクティブを指定する必要があります-lm。POSIX では、c99 コンパイラが をサポートし-lm、ヘッダー<math.h>、<complex.h>、およびで宣言された関数が が指定され<fenv.h>ている場合はリンク可能であることを要求しています-lmが、これらの関数がデフォルトでリンクされるかどうかは指定されていません。[ 11 ] musl は、すべてを単一の libc ライブラリにまとめ、空の libm を提供することでこの要件を満たしています。[ 12 ]
C 標準によれば、実装がホストされている場合はマクロ__STDC_HOSTED__を に定義する必要があります。ホストされた実装には、C 標準で指定されているすべてのヘッダーが含まれています。実装はフリースタンディングであることもできます。これは、標準のフリースタンディング実装の一部となることが保証されているヘッダーのみが存在することを意味します。実装がフリースタンディングである場合は、に定義する必要があります。1__STDC_HOSTED__0
C標準ライブラリの一部の関数は、採用以来、バッファオーバーフローの脆弱性があり、一般的にバグのあるプログラミングを助長することで悪名高い。 [ 13 ] [ a ]最も批判されている項目は以下のとおりである。
strcpy()(およびを含む)は、境界チェックstrcat()が欠如しており、境界を手動でチェックしない場合はバッファオーバーフローが発生する可能性があります。printf()フォーマット文字列が引数と一致しない場合に実行スタックを破損させるためのルーチン群。この根本的な欠陥により、フォーマット文字列攻撃という一連の攻撃が生まれました。gets()また、scanf()入力長チェック機能が(全くないか、あるいは簡単に)ないため、入出力ルーチン群にも影響が出ます。の極端なケースを除きgets()、メモリ管理、境界チェック、入力チェックなどを実行する補助コードを導入することで、すべてのセキュリティ脆弱性を回避できます。これは多くの場合、標準ライブラリ関数をより安全かつ使いやすくするラッパーの形で行われます。この手法は、 B. KernighanとR. Pikeによる『プログラミングの実践』という書籍にまで遡り、著者らはエラーが発生した場合にエラーメッセージを表示してプログラムを終了するラッパーをよく使用しています。
ISO C 委員会は、境界チェックと自動バッファ割り当てを備えたいくつかの関数の採用を提案するために、技術レポート TR 24731-1 [ 14 ]を公開し、TR 24731-2 [ 15 ]に取り組んでいます。前者は厳しい批判と称賛を受けており[ 16 ] [ 17 ]、後者は賛否両論の反応を受けています。
懸念にもかかわらず、TR 24731-1 は ISO/IEC 9899:2011 (C11)、附属書 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、「glibc の現在の (バージョン 2.8) の状況は混乱しています。ほとんどの (すべてではない) 関数はエラー時に例外を発生させます。一部の関数はerrnoも設定します。いくつかの関数はerrnoを設定しますが、例外は発生しません。ごく少数の関数はどちらも行いません。」[ 20 ]
COBOLやFortranといった従来の言語とは異なり、オリジナルのC言語には入出力操作などの組み込み関数は存在しませんでした。時を経て、C言語のユーザーコミュニティは、現在C標準ライブラリと呼ばれるもののアイデアや実装を共有していきました。これらのアイデアの多くは、最終的に標準化されたC言語の定義に組み込まれました。
UnixとC言語はどちらも、 1960年代後半から1970年代初頭にかけてAT&Tのベル研究所で開発されました。1970年代にはC言語の人気が高まり、多くの大学や組織が独自のプロジェクトのために独自のC言語の派生版を作成し始めました。1980年代初頭には、さまざまなC言語の実装間の互換性の問題が明らかになりました。1983年、米国規格協会(ANSI)は、「 ANSI C 」として知られるC言語の標準仕様を確立するための委員会を設立しました。この作業は、1989年にいわゆるC89規格の作成という形で結実しました。その結果として作成された規格の一部には、ANSI C標準ライブラリと呼ばれるソフトウェアライブラリのセットが含まれていました。
Unix系システムなど一部のオペレーティングシステムは、C標準ライブラリと、そのオペレーティングシステム固有のその他のプログラミングインターフェースの両方を含むシステムライブラリを提供している。
POSIXおよびSingle Unix Specification は、基本的な C 標準ライブラリに含まれるルーチンに加えて、多数のルーチンを規定しています。POSIX 仕様には、マルチスレッド プログラム用のPOSIX スレッド、ネットワーク用のBerkeley ソケット、正規表現などの機能のヘッダー ファイルが含まれています。これらは、さまざまな程度の密接さで、C 標準ライブラリの機能と並行して実装されることがよくあります。たとえば、glibc はなどの関数を内で実装していますが、ネイティブ POSIX スレッド ライブラリが glibc に統合される前は、独自のリンカー フラグ引数を持つ別のライブラリでした。多くの場合、この POSIX で規定された機能はライブラリの一部とみなされ、基本的な C ライブラリは ANSI またはISO C ライブラリとして識別されることがあります。forklibc.so
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()そして、およびの安全な代替手段[ 32 ] [ 33 ] [ 34 ] [ 35 ] [ 36 ]strlcpy() strncat()strncpy()<err.h> –フォーマットされたエラーメッセージを出力する関数が含まれています[ 37 ] [ 38 ]<vis.h> –関数が含まれていますvis()。この関数は、印刷不可能な文字を視覚的な形式で表示するために使用されます。[ 39 ] [ 40 ] [ 41 ]一部のプログラミング言語は、標準Cライブラリの機能を独自のライブラリに組み込んでいる。ライブラリは言語の構造に合わせて調整される場合もあるが、操作的な意味論は基本的に同じまま維持される。
C ++言語は、C標準ライブラリの構成要素の大部分を、C固有の機構を除いて、自らの言語に取り込んでいます。C標準ライブラリの関数は、C++標準ライブラリから2つの方法でエクスポートされます。
C および標準以前の C++ との後方互換性および相互互換性のために、関数はC と同様に C 標準ヘッダー名を付けた後、グローバル名前空間( ::) でアクセスできます。[ 42 ]#includeしかし、::グローバル名前空間を示すために使用されるものは、同じシンボル名が定義されている他の名前空間の範囲内にある場合にのみ必要です。したがって、C++98 プログラム
#include <stdio.h>int main ( void ) { return puts ( "Hello, world!" ) == EOF ; }コードが同一のC95プログラムと(見た目上)同一の動作を示すはずである。
C++98以降、C関数は対応するCヘッダーの代わりにヘッダーを含めることで、名前空間内でも利用できるようになりましたstd(例:Cを printfC++として std::printf、atoiをstd::atoi、feofをとして) 。例:はを、をに置き換えます。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 ]
その他はプレースホルダーに縮小され、例えば(C++20までは)<ciso646>C95<iso646.h>のマクロはすべて C++98 でキーワードとしてレンダリングされる。C 固有の構文構造は、ヘッダーがサポートされていても、一般的にはサポートされていない。[ 45 ]
いくつかのCヘッダーは主にC++との 互換性のために存在し、C++ではこれらはほとんど空になる傾向があります。たとえば、C99-17では、<stdbool.h>
#define bool _Bool #define false 0 #define true 1 #define __bool_true_false_are_defined 1boolC++98 の、false、 およびキーワードのサポートを装うため、C++11trueでは互換性のためにと が必要ですが、 を定義するだけで済みます。C23では古いキーワード を非推奨とし、新しい C++98 相当の、、 およびキーワードを採用しているため、C≥23 と C++≥11 / のヘッダーは完全に同等です。(特に、C23では のマクロは不要です。)<stdbool.h><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、write、など)は、対応するC関数( fopen、、など)と同じ動作をすることが期待されます。freadfwrite
しかし、 Python 3の仕様は、 Python 2に比べて C 言語特有の仕様への依存度がかなり低い。
Rust はlibc、さまざまな C 標準 (およびその他の) ライブラリ関数と型定義を使用できるcrate を提供しています。 [ 49 ]
C言語の標準ライブラリは、他の言語の標準ライブラリと比べると小規模です。Cライブラリは、基本的な数学関数、文字列操作、型変換、ファイルおよびコンソールベースの入出力機能を提供します。C ++標準テンプレートライブラリのような標準的な「コンテナ型/コレクション型」は含まれておらず、 Javaや.NET Frameworkが標準で提供するような完全なグラフィカルユーザーインターフェース(GUI)ツールキット、ネットワークツール、その他多数の機能も含まれていません。標準ライブラリが小規模であることの主な利点は、他の言語に比べて動作するISO C環境をはるかに容易に提供できることであり、その結果、C言語を新しいプラットフォームに移植することが比較的容易になります。
単一の
ステートメントが、プロジェクト全体の名前空間管理を混乱させる可能性があります。したがって、
ヘッダーファイルには
トップレベルの [ ] ステートメントは使用しないでください。
using namespace std;using namespace
ファイルオブジェクトはCの
stdio
パッケージを使用して実装されており、組み込み
関数で作成できます。
open()