C(プログラミング言語)
| C | |
|---|---|
『プログラミング言語C』初版の表紙に使用されたロゴタイプ[ 1 ] | |
| パラダイム | マルチパラダイム:命令型(手続き型)、構造化 |
| デザイン: | デニス・リッチー |
| 開発者 | ANSI X3J11 ( ANSI C ); ISO/IEC JTC 1 (合同技術委員会 1) / SC 22 (小委員会 22) / WG 14 (ワーキンググループ 14) (ISO C) |
| 初登場 | 1972年[ a ] |
| 安定版リリース | C23 / 2024年10月31日 |
| プレビューリリース | |
| タイピングの規律 | 静的、弱い、顕在的、名目上の |
| OS | クロスプラットフォーム |
| ファイル名拡張子 | .c、.h |
| Webサイト | |
| 主要な実装 | |
| pcc、GCC、Clang、Intel C、C++Builder、Microsoft Visual C++、Watcom C | |
| 方言 | |
| Cyclone、Unified Parallel C、Split-C、Cilk、C* | |
| 影響を受けた | |
| B、BCPL、CPL、ALGOL 68、[ b ] PL/I、Fortran | |
| 影響を受けた | |
| 多数:AMPL、AWK、csh、C++、C--、C#、Objective-C、D、Go、Java、JavaScript、JS++、Julia、Limbo、LPC、Perl、PHP、Pike、Processing、Python、Rust、V(Vlang)、Vala、Verilog(HDL)、[ 8 ] Nim、Zig | |
| |
| この記事はCプログラミング言語に関するシリーズの一部です。 |
C [ c ]は、1970年代にデニス・リッチーによって作成された汎用プログラミング言語です。C言語の設計により、プログラマはターゲット命令セットに合わせてカスタマイズされた典型的なCPUアーキテクチャの機能に比較的直接的にアクセスできます。オペレーティングシステム(特にカーネル[ 10 ])、デバイスドライバ、プロトコルスタックの実装には使用されてきましたが、現在も使用されています。しかし、アプリケーションソフトウェアでの使用は減少しています。[ 11 ] C言語は、最大規模のスーパーコンピュータから最小規模のマイクロコントローラや組み込みシステムに至るまで、幅広いコンピュータで使用されています。
プログラミング言語Bの後継であるC は、もともと1972 年から 1973 年にかけてベル研究所でリッチーによってUnix上で実行されるユーティリティを構築する目的で開発されました。これは、 Unix オペレーティングシステムのカーネルの再実装に適用されました。[ 12 ] 1980 年代に、C は徐々に人気を集めました。最も広く使用されているプログラミング言語の 1 つになり、[ 13 ] [ 14 ] Cコンパイラは、実質的にすべての最新のコンピュータアーキテクチャとオペレーティングシステムで使用できます。元の言語設計者が共著した書籍「プログラミング言語 C 」は、長年にわたってこの言語の事実上の標準となりました。 [ 15 ] [ 1 ] C は、1989 年以来米国規格協会(ANSI)によって標準化されており、その後、国際標準化機構(ISO) と国際電気標準会議(IEC) によって共同で標準化されています。
C言語は命令型の手続き型言語であり、構造化プログラミング、語彙的変数スコープ、再帰をサポートし、静的型システムを備えています。C言語は、メモリへの低レベルアクセスと、機械語命令に効率的にマッピングされる言語構造を、最小限のランタイムサポートで提供するようにコンパイルされるように設計されています。低レベルの機能にもかかわらず、C言語はクロスプラットフォームプログラミングを促進するように設計されています。移植性を考慮して記述された標準準拠のCプログラムは、ソースコードをほとんど変更することなく、様々なコンピュータプラットフォームやオペレーティングシステム向けにコンパイルできます。
C言語とその標準ライブラリは、他の言語で見られるような一般的な機能のいくつかを提供していませんが、それらをサポートできるほど柔軟です。例えば、オブジェクト指向とガベージコレクションは、それぞれ外部ライブラリのGLib Object SystemとBoehmガベージコレクタによって提供されています。
2000年以降、C言語はTIOBEインデックスで最も人気がある言語、または2番目に人気のある言語としてランク付けされています。[ 16 ]
特徴

C 言語には次のような特徴があります。
- 自由形式のソースコード
- セミコロンは文を終了します
- 中括弧は文をブロックにグループ化します
- 実行可能なコードは関数内に含まれている(スクリプトのような構文はない)
- パラメータは値渡しされ、参照渡しは値へのポインタを渡すことによって実現されます。
- キーワードの数が比較的少ない
if、、、、およびforを含む制御フロー構造dowhileswitch- 算術演算子、ビット演算子、論理演算子(、、、、
+を含む)+=++&|| - 1つの文で複数の代入が実行できる
- ユーザー定義の識別子はキーワードと区別されません(つまり、シギルによって)
- ブロック内で宣言された変数は、そのブロック内でのみ、宣言の下のみアクセス可能です。
- 関数の戻り値は無視できる
- 関数を関数内にネストすることはできませんが、一部の翻訳者はこれをサポートしています。
- 実行時の多態性は関数ポインタを使用して実現できる。
- 再帰をサポート
- データの型付けは静的ですが、強制は弱いです。すべての変数には型がありますが、プリミティブ型間の暗黙的な変換により、異なる型の分離が弱まります。
- ユーザー定義データ型ではデータ型指定子の別名が使用可能
- 配列の定義とアクセスの構文は、例えば のように、角括弧記法で表されます
month[11]。インデックスはポインタ演算によって定義されます。カスタムコードまたはライブラリコードなしでは、配列全体をコピーまたは比較することはできません。 - ユーザー定義の構造型では、関連するデータ要素をユニットとして渡したりコピーしたりできますが、各フィールドを比較するカスタムコードがなければ 2 つの構造を比較することはできません。
- ユーザー定義のユニオン型は重複メンバーをサポートし、複数のデータ型が同じメモリ位置を共有できるようにします。
- ユーザー定義の列挙型は整数値のエイリアスをサポートします
- 文字列型はないが、標準ライブラリに関連する処理を備えたヌル終端文字列の構文がある。
- ポインタを介してコンピュータメモリへの低レベルアクセスをサポートします
- 関数を返すプロシージャのような構造をサポートします
void - 標準ライブラリ関数による動的メモリのサポート
- マクロ定義、ソースコードファイルのインクルード、条件付きコンパイルを実行するためのC プリプロセッサが含まれています。
- ファイルは個別に処理され、属性による可視性制御が行われるというモジュール性をサポートします。
staticextern - コア言語の機能は最小限に抑えられ、I/O、文字列操作、数学関数などの比較的複雑な機能は標準ライブラリ関数でサポートされます。
- 結果として得られるコンパイルされたコードは、基盤となるプラットフォーム上で比較的単純な要件を満たすため、オペレーティングシステムや組み込みシステムに適しています。
「Hello, world」の例

K&Rの初版に掲載された「Hello, World!」プログラム例は、多くのプログラミング教科書の入門プログラムのモデルとなっています。このプログラムは標準出力に「hello, world」と出力します。
元のバージョンは次の通りです。[ 17 ]
main () { printf ( "hello, world \n " ); }より現代的なバージョンは次のとおりです: [ d ]
#include <stdio.h>int main ( void ) { printf ( "hello, world \n " ); }最初の行は、 で示されるプリプロセッサ指令#includeであり、これによりプリプロセッサは、そのコード行をstdio.h、 を含む入出力関数の宣言を含むヘッダーファイルのテキストに置き換えますprintf。 を囲む山括弧はstdio.h、プロジェクト固有のディレクトリにある同じ名前のファイルよりもコンパイラに付属のヘッダーファイルを選択する検索戦略を使用して、ヘッダーファイルを見つけることができることを示します。
次のコード行は、エントリポイント関数を宣言していますmain。ランタイム環境はこの関数を呼び出してプログラムの実行を開始します。型指定子は、int関数が整数値を返すことを示しています。voidパラメータリストは、関数が引数を取らないことを示しています。ランタイム環境は実際には2つの引数(型付きintとchar *[])を渡しますが、この実装ではそれらを無視します。ISO C規格(セクション5.1.2.2.1)では、voidまたはこれら2つの引数のいずれかを使用する構文が要求されています。これは他の関数には適用されない特別な扱いです。
開き中括弧は、関数を定義するコードの開始を示します。
次のコード行は、文字列リテラルとして指定されたヌル終端文字列の先頭文字のprintfアドレスを使用して、C標準ライブラリ関数を呼び出します(実行をその関数に転送します) 。テキストは改行文字を表すエスケープシーケンスであり、端末に出力された場合にはカーソルを次の行の先頭に移動します。戻り値は返されますが、暗黙的に破棄されます。セミコロンは呼び出し文を終了します。 \nprintfint;
閉じ括弧はmain関数の終了を示します。C99より前では、関数return 0;の終了時に明示的な文が必要でしたmainが、C99以降では、main関数(最初の関数呼び出し)は0最後の閉じ括弧に達すると暗黙的に戻ります。[ e ]
歴史
初期の開発
| 年 | 通称 | 公式規格 |
|---|---|---|
| 1972 | 最初のリリース | 該当なし |
| 1978 | K&R C | 該当なし |
| 1989年、1990年 | ANSI C、C89、ISO C、C90 | ANSI X3.159-1989 ISO/IEC 9899:1990 |
| 1999 | C99、C9X | ISO/IEC 9899:1999 |
| 2011 | C11、C1X | ISO/IEC 9899:2011 |
| 2018 | 17世紀、18世紀 | ISO/IEC 9899:2018 |
| 2024 | C23、C2X | ISO/IEC 9899:2024 |
| 未定 | C2Y |
C言語の起源は、 Unixオペレーティングシステムの開発と密接に結びついています。Unixオペレーティングシステムは、当初はデニス・リッチーとケン・トンプソンによってPDP-7上でアセンブリ言語で実装され、同僚のアイデアも取り入れられました。最終的に、彼らはオペレーティングシステムをPDP-11に移植することを決定しました。オリジナルのPDP-11版Unixもアセンブリ言語で開発されました。[ 12 ]
B
トンプソンは、新しいプラットフォーム用のユーティリティを開発するためのプログラミング言語を求めていました。最初はFortranコンパイラを書こうとしましたが、すぐに断念し、代わりに当時開発されていたシステムプログラミング言語BCPLの簡略版を作成しました。当時、BCPLの公式説明はありませんでしたが[ 19 ] 、トンプソンは構文をより簡潔にし、SMALGOLとして知られる簡略化されたALGOLに似たものにしました。 [ 20 ]彼はその結果をBと呼び、[ 12 ]「多くのSMALGOL構文を持つBCPLセマンティクス」と表現しました。[ 20 ] BCPLと同様に、Bには新しいマシンへの移植を容易にするためのブートストラップコンパイラがありました。[ 20 ]結局、Bは速度が遅すぎて、バイトアドレス指定などのPDP-11の機能を利用できなかったため、Bで書かれたユーティリティはほとんどありませんでした。
BCPLが// comment行末までコメントをマークするのとは異なり、Bは/* comment */PL/1に似たコメント区切り文字を採用し、行の途中にコメントを記述できるようにしました。(BCPLのコメントスタイルはC++で再導入されました。)[ 12 ]
新しいBと最初のCリリース
1971年、リッチーはより強力なPDP-11の機能を利用するためにB言語の改良に着手した。重要な追加要素は文字データ型であり、彼はこれをNew B(NB)と名付けた。[ 20 ]トンプソンはNB言語を用いてUnixカーネルの開発を開始し、彼の要求が言語開発の方向性を決定づけた。[ 20 ] [ 21 ]
1972年までに、NB言語にはより豊富な型が追加されました。NBには配列とがありint、charこれらの型に加えてポインタ、他の型へのポインタを生成する機能、あらゆる型の配列、そして関数から返される型が追加されました。式内の配列は実質的にポインタとして扱われました。新しいコンパイラが開発され、言語はCと改名されました。[ 12 ]
Cコンパイラとそれを使って作られたいくつかのユーティリティは、 Research Unixとしても知られるVersion 2 Unixに含まれていました。[ 22 ]
構造体とUnixカーネルの書き換え
1973年11月にリリースされたバージョン4 Unixでは、UnixカーネルがCで広範囲に再実装されました。[ 12 ]この頃には、C言語は型などの強力な機能をいくつか獲得していましたstruct。
このプリプロセッサは、アラン・スナイダーの提唱と、BCPLおよびPL/Iのファイルインクルード機構の有用性への認識により、 1973年頃に導入されました。当初のバージョンでは、インクルードファイルと単純な文字列置換、#includeそしてパラメータなしのマクロしか提供されていませんでした。その後まもなく、主にマイク・レスク、そしてジョン・ライザーによって#define拡張され、引数付きマクロと条件付きコンパイルが組み込まれました。[ 12 ]
Unixは、アセンブリ言語以外の言語で実装された最初のオペレーティングシステムカーネルの一つです。初期の例としては、Multicsシステム( PL/Iで記述)や、 1961年のBurroughs B5000用のMaster Control Program(MCP) ( ALGOLで記述)などがあります。1977年頃、RitchieとStephen C. Johnsonは、 Unixオペレーティングシステムの移植性を高めるために、言語にさらなる変更を加えました。JohnsonのPortable C Compilerは、新しいプラットフォームにおけるCのいくつかの実装の基礎となりました。[ 21 ]
K&R C

1978年、ブライアン・カーニハンとデニス・リッチーは『プログラミング言語C』の初版を出版した。[ 23 ]著者の頭文字からK&Rとして知られるこの本は、長年にわたり言語の非公式仕様書として用いられた。本書で解説されているCのバージョンは、一般的に「K&R C 」と呼ばれている。これは1978年に出版されたため、現在ではC78とも呼ばれる。[ 24 ]本書の第2版[ 25 ]は、後述する後のANSI C規格を網羅している。
K&Rではいくつかの言語機能が導入されました。
- 標準I/Oライブラリ
long intデータ型unsigned intデータ型- 形式( など) の複合代入演算子は、形式(つまり) に変更されました。これは、 などの構文によって生じる意味の曖昧さを解消するためです。この構文は、おそらく意図されていた( -10 にする) ではなく、 (10 で減分する)と解釈されていました。
=op=-op=-=i=-10i =- 10ii = -10i
1989 年の ANSI 標準が公開された後も、多くの古いコンパイラがまだ使用されており、また慎重に記述された K&R C コードは合法的な標準 C でもある可能性があるため、長年にわたり K&R C は C プログラマーが最大限の移植性を望む場合に自らを制限する「最低共通分母」であると考えられていました。
C言語の後のバージョンでは関数に明示的な型宣言が必要になりましたが、K&R Cでは、 以外の型を返す関数のみint使用前に宣言する必要があります。事前の宣言なしに使用される関数は、 を返すものとみなされますint。
例えば:
長いlong_function ();呼び出し関数(){長いlongvar ;intvarを登録します。longvar = long_function ();(longvar > 1 )の場合intvar = 0 ;それ以外intvar = int_function ();intvarを返します。}(1行目)の宣言はlong_function()必須です。これは を返すためlong、 は返しませんint。関数int_functionは を返すため、宣言されていなくても(11行目)呼び出すことができますint。また、変数はキーワードのデフォルト型であるため、intvarとして宣言する必要はありません。 intregister
関数宣言には引数に関する情報が含まれていなかったため、型チェックは行われませんでしたが、一部のコンパイラは、関数呼び出しごとに異なる数や型の引数が使用された場合、警告を発していました。Unixのlintユーティリティなどのツールは、複数のソースファイル間での関数の使用の一貫性をチェックするなど、様々な機能を備えていました。
K&R Cの出版後数年間で、AT&T(特にPCC [ 26 ])や他のベンダーのコンパイラによってサポートされたいくつかの機能が言語に追加された。これには以下が含まれる。
言語の人気、標準ライブラリインターフェースの合意の欠如、K&R仕様への準拠の欠如が、標準化の取り組みにつながりました。[ 27 ]
ANSI C および ISO C
1970 年代後半から 1980 年代にかけて、 C の人気が高まり 、 IBM PCを含むさまざまなメインフレーム コンピュータ、ミニコンピュータ、マイクロコンピュータに C のバージョンが実装されました。
1983年、米国規格協会(ANSI)はC言語の標準仕様を策定するために委員会X3J11を設立しました。X3J11はC言語標準をUnix実装に基づいて策定しましたが、Unix Cライブラリの非移植部分はIEEEワーキンググループ1003に引き継がれ、1988年のPOSIX標準の基礎となりました。1989年、C言語標準はANSI X3.159-1989「プログラミング言語C」として承認されました。このバージョンの言語は、 ANSI C、標準C、あるいはC89と呼ばれることもあります。
1990年、ANSI C規格(フォーマットの変更を含む)は、国際標準化機構(ISO)によってISO/IEC 9899:1990として採択されました。これはC90と呼ばれることもあります。そのため、「C89」と「C90」という用語は同じプログラミング言語を指します。
ANSIは、他の国家標準化団体と同様に、C言語規格を独自に開発することはなくなり、ISO/IEC JTC1/SC22 /WG14ワーキンググループが維持する国際C言語規格に準拠するようになりました。国際規格の更新版は、通常、ISO発行後1年以内に各国で採用されます。
C標準化プロセスの目的の一つは、後に導入された多くの非公式機能を組み込んだK&R Cのスーパーセットを作成することでした。標準化委員会は、関数プロトタイプ(C++から借用)、voidポインタ、国際文字セットとロケールのサポート、プリプロセッサの拡張など、いくつかの追加機能も取り入れました。パラメータ宣言の構文はC++で使用されるスタイルを含むように拡張されましたが、既存のソースコードとの互換性を保つため、K&Rインターフェースは引き続き認められました。
C89は現在のCコンパイラでサポートされており、現代のCコードのほとんどはこれに基づいています。ハードウェア依存の仮定を一切せずに標準Cのみで記述されたプログラムは、準拠したC実装を持つあらゆるプラットフォームにおいて、そのリソース制限内で正しく動作します。このような予防措置を講じないと、例えばGUIライブラリなどの非標準ライブラリの使用、あるいはデータ型の正確なサイズやバイトエンディアンといったコンパイラまたはプラットフォーム固有の属性への依存などにより、特定のプラットフォームまたは特定のコンパイラでしかコンパイルできない場合があります。
コードを標準準拠コンパイラまたは K&R C ベースのコンパイラでコンパイルする必要がある場合、__STDC__マクロを使用してコードを標準セクションと K&R セクションに分割し、K&R C ベースのコンパイラで標準 C でのみ利用可能な機能が使用されるのを防ぐことができます。
ANSI/ISO標準化プロセスの後、C言語仕様は数年間比較的静的なままでした。1995年には、1990年版C規格の規範的修正第1版(ISO/IEC 9899/AMD1:1995、通称C95)が発行され、いくつかの詳細が修正され、国際文字セットのサポートがより広範囲に拡張されました。[ 28 ]
C99
C規格は1990年代後半にさらに改訂され、1999年にISO/IEC 9899:1999(通称「C99」)が発行されました。その後、技術訂正によって3回改訂されています。[ 29 ]
C99では、インライン関数、いくつかの新しいデータ型(複素数を表す型long long intを含む)、可変長配列と柔軟な配列メンバー、 IEEE 754浮動小数点のサポートの改善、可変引数マクロ(可変引数のマクロ)のサポート、BCPLやC++のように で始まる1行コメントのサポートなど、いくつかの新機能が導入されました。これらの多くは、すでにいくつかのCコンパイラで拡張機能として実装されていました。 complex//
C99はC90と大�