C言語(シーげんご、英: C programming language)は、1972年にAT&Tベル研究所のデニス・リッチーが主体となって開発した汎用プログラミング言語である。英語圏では「C language」または単に「C」と呼ばれることが多い。日本でも文書や文脈によっては同様に「C」と呼ぶことがある。制御構文などに高水準言語の特徴を持ちながら、ハードウェア寄りの記述も可能な低水準言語の特徴も併せ持つ。基幹系システムや、動作環境の資源制約が厳しい、あるいは実行速度性能が要求されるソフトウェアの開発に用いられることが多い。後発のC++やJava、C#など、「C系」と呼ばれる派生言語の始祖でもある。
C言語のロゴ | |
パラダイム | 命令型プログラミング、構造化プログラミング、手続き型プログラミング |
---|---|
登場時期 | 1972年 . |
開発者 | ベル研究所、デニス・リッチー、米国国家規格協会、国際標準化機構、ケン・トンプソン |
最新リリース | ISO/IEC 9899:2018/ 2018年 |
型付け | 弱い静的型付け |
主な処理系 | GCC, Clang, Visual C++, Intel C++ Compiler |
影響を受けた言語 | ALGOL 68、B言語、アセンブリ言語、FORTRAN、PL/I、CPL、BCPL、ALGOL 60、ALGOL |
影響を与えた言語 | awk、csh、C++、Objective-C、Rust、D言語、Java、JavaScript、Limbo |
プラットフォーム | Microsoft Windows、Unix系 |
ウェブサイト | |
拡張子 | .c , .h |
この節に雑多な内容が羅列されています。 |
Cには他のプログラミング言語と比較して、特筆すべきいくつかの特徴がある。
上記のように、利点でもあり、同時に欠点にもなる特徴を備えている。
もともとUNIXおよびCコンパイラの移植性を高めるために開発されてきた経緯から、オペレーティングシステム(OS)のカーネルおよびコンパイラ向けの低水準な記述ができるなど、ハードウェアをある程度抽象化しつつも、必要に応じて低水準言語と同じことを実現できるようなコンピュータ寄りの言語仕様になっている。そのため、低水準な記述ができる高水準言語と言われたり、高水準言語の顔をした低水準言語(高級アセンブラ、汎用アセンブラ)と言われたりすることがある。
Cはアマチュアからプロ技術者まで、プログラマ人口が多く、プログラマのコミュニティが充実している。使用者の多さから、正負の両面含め、Cはプログラミング文化に大きな影響を及ぼしている。また、多目的性と、対応機器の多彩さのため、「コンピュータを使ってやること」は大抵、Cで対応可能である。ただし、Cで効率的かつ安全に記述できるかどうかはまた別の話である。スクリプト言語やコマンドラインシェルを使えば手軽に実現にできるような処理まで、わざわざCで記述する必要はない。また、GUIアプリケーションフレームワークは、Cからは利用できず、統合開発環境と連携する新しいプログラミングツールやプログラミングパラダイムに対応した後発言語でなければ利用できないものもある。
MISRA CやCERT Cというコーディング標準(コーディング規約)を定義して、危険な機能の使用や記述を禁止するという制限を設けることでCを安全に利用するためのガイドラインが運用されている分野もある。特にプログラミングミスが人命に直結する自動車分野などでCを利用するには、このような制約が重要である。
;
」で表し、改行文字にも空白にもトークンの区切りとしての意味しか持たせない「フリーフォーマット」という形式を採用している。中括弧{ }
によるブロック構造およびスコープをサポートする。goto
)を使用する必要はなく、MISRA Cでは当初goto文を禁止していた。main
という名前の関数として定義する。プログラム中で再帰的にmain
関数を呼ぶことも可能(C++では不可能)。フリースタンディング環境では、エントリーポイントと呼ばれるアドレスに置かれたコードをプログラムの開始点とするが、それがmain関数である必要はない。なお再帰呼び出しそのものは、スタックオーバーフローの原因となるため、MISRA Cでは禁止している。int
型とみなし、関数の戻り値の型指定がない場合はint
型とみなす。ANSI C (C89) ではコンパイル時型検査の強化のために関数プロトタイプの機能が導入されたが、関数の宣言がない場合の戻り値はint
型とみなし、引数は未知(任意)とみなす。しかし、このような暗黙の型指定は型安全性を損ない未定義動作を引き起こす危険性があるため、ISO/IEC C:1999 (C99) 以降では暗黙の型指定に関する仕様が標準規格の文面から削除された。いずれも使用(参照)するより前に適切に宣言する必要がある。ClangやGCCといったC99準拠のコンパイラは、このような暗黙の型指定について、C99モードであってもC89互換の動作を残してはいるものの、非標準の動作であるため警告を出すようになっている。なお、関数宣言において()
のように引数を省略すると、引数を未知とする仕様はC99でも残されている。後継言語では完全なプロトタイプ宣言を必須とするか、あるいはプロトタイプ宣言自体を不要としているが、記述によっては先読みが必要になりうる。処理系の簡素化のため、以下のように安全性を犠牲にした仕様が多い。なお、ホスト環境やプログラムの内容によっては、以下に対して脆弱性対策を施したとしても実行速度の低下が無視できる程度であることも多く、言語仕様側の欠点とみなされることも少なくない。
char
型の配列を利用する。言語仕様上に特別な扱いはないが、ヌル文字('\0'
)を終端とする文字列表現を使い、その操作をする標準ライブラリ関数がある。これは実質的にメモリ領域のポインタアクセスそのもので、固定長バッファに対して、それより長い可変長の文字列を書き込んでしまうことがあり、バッファオーバーランの元凶の1つとなっている。malloc
およびその類似関数にて提供される。一方、カーネルではメモリ確保の際にスレッドがブロックされるとカーネル内のデータが他のスレッドにより変更され、予期せぬ動作を起こす恐れがあることや、メモリ内容の初期化が必要かどうかによって割当先のページを選択することによりシステムの効率が上がることから、多くの場合POSIXとは異なるAPIを使用している。Linuxカーネルの場合、前者はフラグGFP_KERNEL
とGFP_ATOMIC
の使い分け、後者は関数kmalloc
(割り当てたメモリの内容は不定)とkzalloc
(割り当てたメモリの内容はゼロクリア済)の使い分けにより実装している。C言語のHello worldプログラムは、ホスト環境を前提とするか、フリースタンディング環境を前提とするかで、方向性が異なる。ホスト環境を前提とする場合には、標準入出力の利用により、動作をすぐに確かめることができる。以下では、標準Cライブラリのヘッダstdio.h
にて宣言されている、puts
関数あるいはprintf
関数を利用したものを例示する。
/* int puts(const char* s) を使う場合。 */ #include int main(void) { puts("Hello, world!"); return 0; }
/* int printf(const char* format, ...) を使う場合。 */ #include int main(int argc, char* argv[]) { printf("Hello, world!\n"); return 0; }
上記サンプルソース中の「\n
」は、エスケープ文字\
によるエスケープシーケンスのひとつであり、改行(ラインフィード)を表す。
main
関数は標準的なプログラムエントリーポイントであり、プログラムを開始すると、ランタイムライブラリによるスタートアップ処理が実行された後にこのmain
関数が呼ばれる。引数のないバージョンと、コマンドライン引数をポインタ配列として受け取るバージョンどちらを使ってもよい。
なお、printf
関数は書式文字列とそれに対応する可変個引数を受け取り、書式化された文字列として表示できる高機能な標準出力関数であるが、序盤から例示に使用している入門書もある。
main
関数とprintf
関数は、いずれも入門者や初学者にとっては最初の関門となる難解な関数であり、C言語によるプログラミングのハードルを高くしている一因でもある。JavaやC#のような後発言語では、文字列の扱いや、可変個引数の扱いがより簡潔で安全になっている。Pythonのようなインタプリタや対話環境上で動作することを前提とした言語では、main
関数を定義する必要はない。
C言語は、AT&Tベル研究所のケン・トンプソンが開発したB言語の改良として誕生した(#外部リンクの「The Development of the C Language」参照)。
1972年、トンプソンとUNIXの開発を行っていたデニス・リッチーはB言語を改良し、実行可能な機械語を直接生成するC言語のコンパイラを開発した。後に、UNIXは大部分をC言語によって書き換えられ、C言語のコンパイラ自体も移植性の高い実装のPortable C Compilerに置き換わったこともあり、UNIX上のプログラムはその後にC言語を広く利用するようになった。
ちなみに、「UNIXを開発するためにC言語が作り出された」と言われることがあるが、「The Development of the C Language」によると、これは正しくなく、経緯は以下の通りである。C言語は、当初はあくまでもOS上で動くユーティリティを作成する目的で作り出されたものであり、OSのカーネルを記述するために使われるようになるのは後の展開である。
アセンブラとの親和性が高いために、ハードウェアに密着したコーディングがやりやすかったこと、言語仕様が小さいためコンパイラの開発が楽だったこと、小さな資源で動く実行プログラムを作りやすかったこと、UNIX環境での実績があり、後述のK&Rといった解説文書が存在していたことなど、さまざまな要因からC言語は業務開発や情報処理研究での利用者を増やしていった。特にメーカー間でオペレーティングシステムやCPUなどのアーキテクチャが違うUNIX環境では再移植の必要性がしばしば生じて、プログラムをC言語で書いてソースレベル互換を確保することが標準となった。
C言語の開発当初に使われた入力端末はASR-37であったことが知られている。 ASR-37は1967年制定の旧ASCII ISO R646-7bitにもとづいており、「{
」および「}
」の入力を行うことができたが、当時は一般的に使われていた入力端末ではなかった。 当時PDP-11の入力端末として広く使われていたのはASR-33であるが、これは1963年制定の旧ASCIIであるASA X3.4に準拠しており、「{
」や「}
」の入力を行うことはできなかった。
このことは、ブロック構造に「{
」や「}
」を用いるC言語(さらに元をたどればB言語)は、当時の一般的な環境では使用不可能であったことを示している。 これは、C言語はその誕生当初にあっては一般に広く使われることを想定しておらず、ベル研究所内部で使われることを一義的に考えた言語であったという側面の表れである。
これに対し、PascalやBASIC等の当初から広く使われることを想定した言語では、ブロック構造に記号を用いずにbegin
とend
をトークンとして用いることや、コメント行を表す際に開始トークンとしてREM
という文字列を用いることなど、記号入力に制約がある多くの入力端末に対応できるように配慮されていた。この頃の他の言語やOSで大文字と小文字の区別をしないものが多いのも、当時は大文字しか入力できない環境も少なくなかったことの表れである。
このような事情のため、C言語が普及するのは、ASCII対応端末が一般化した1980年代に入ってからである。
現在、ブロック構造の書式等で、{...}
形式のC言語と、begin...end
等を使用する他の言語との比較において優劣を論じられることがあるが、開発時の環境等をふまえずに現時点での利便性のみで論じるのは適切ではない場合があることに留意が必要である。
1980年代に普及し始めたパーソナルコンピュータ (PC) は当初、8ビットCPUでROM-BASICを搭載していたものも多く、BASICが普及していたが、1980年代後半以降、16ビットCPUを採用しメモリも増えた(ROM-BASIC非搭載の)PCが主流になりだすと、Turbo CやQuick Cといった2万円程度の比較的安価なコンパイラが存在したこともあり、ユーザーが急増した。8ビットや8086系のPCへの移植は、ポインタなどに制限や拡張を加えることで解決していた。
1990年代中盤には、最初に学ぶプログラミング言語としても主流となった。また、同時期にはゲーム専用機(ゲームコンソール)の性能向上とプログラムの大規模化、マルチプラットフォーム展開を受け、メインの開発言語がアセンブラからC言語に移行した。
1990年代後半から2000年代以降は、PCのさらなる性能向上と普及、GUI環境やオブジェクト指向の普及、インターネットおよびウェブブラウザの普及、スマートフォンの普及に伴い、より高水準で開発効率の高い言語やフレームワークを求める開発者が増えたことにより、C++、Visual Basic、Java、C#、Objective-C、PHP、JavaScriptなどが台頭してきた。広く利用されるプログラミング言語の数は増加傾向にあり、相対的にC言語が使われる場面は減りつつある。特にアプリケーションソフトウェアなどの上位層の開発には、C言語よりも記述性に優れるC++、Java、C#などC言語派生の後発言語が利用されることが多くなっている。資源制約の厳しかったゲーム開発においても、ハードウェアの性能向上やミドルウェアの普及により、C++やC#などが使われる場面が増えている。速度性能や省メモリが特に重視されるシステムプログラミングに関しても、伝統的にC/C++の独壇場だったが、新規コードではより安全性の高いRustを導入する事例が現れている。
しかし、C言語は比較的移植性に優れた言語であり、個人開発/業務用開発/学術研究開発やプロプライエタリ/オープンソースを問わず、オペレーティングシステムやデバイスドライバーなどの下位層、クロスプラットフォームAPIの外部仕様、C++やJavaなどの高水準言語の処理系および実行環境の実装が困難な小規模の組み込みシステムなどを中心に、2021年現在でも幅広く利用されている。
プログラミング入門者にとっては、Python、JavaScript、Swift、Kotlinなどのように、インタラクティブな対話環境(REPL、インタプリタ)が利用でき、抽象化が進んでおり、煩雑なメモリ管理が不要で、危険な機能を制限した高水準言語のほうが学習・習得しやすいが、コンピュータの動作原理やハードウェア仕様を理解するには、Cのような原始的な言語を用いたほうがかえって分かりやすいケースもある。
米国国家規格協会(ANSI)による標準化が行われるまで、1978年出版のデニス・リッチーとブライアン・カーニハンの共著『The C Programming Language』が実質的なC言語の標準として参照されてきた。この書籍は、著者らのイニシャルを取って「K&R」とも呼ばれている。C言語は発展可能な言語で、K&Rの記述も発展の可能性のある部分は厳密な記述をしておらず、曖昧な部分が存在していた。そのためC言語が普及するとともに、互換性のない処理系が数多く誕生した。
そこで、ISO/IEC JTC1とANSIは協同でC言語の規格の標準化を進め、1989年12月にANSIがANSI X3.159-1989, American National Standard for Information Systems -Programming Language-Cを、1990年12月にISOがINTERNATIONAL STANDARD ISO/IEC 9899 : 1990(E) Programming Languages-Cを発行した。ISO/IEC規格のほうが章立てを追加しており、その後ANSIもISO/IEC規格にならって章立てを追加した。それぞれC89 (ANSI C89) およびISO/IEC C90という通称で呼ぶことがある。
日本では、これを翻訳したものを『JIS X 3010-1993 プログラム言語C』として、1993年10月に制定した。
最大の特徴は、C++と同様の関数プロトタイプを導入して引数の型チェックを強化したことと、void
やenum
などの新しい型を導入したことである。一方、「処理系に依存するものとする」に留めた部分も幾つかある(int
型のビット幅、char
型の符号、ビットフィールドのエンディアン、シフト演算の挙動、構造体などへのパディング等)。
規格では以下の3種類の自由を認めている部分がいくつかある。
これにより、プラットフォームやプロセッサアーキテクチャとの相性による有利不利が生じないような仕様になっている。
8ビット/16ビット/32ビットなど、レジスタ幅(ワードサイズ)の異なるプロセッサ (CPU) に対応・最適化できるようにするため、組み込み型の情報量(大きさ)や内部表現にも処理系の自由を認めている。型のバイト数はsizeof
演算子で取得し、各型の最小値・最大値はlimits.h
で定義されているマクロ定数で参照することとしている。ただし、1バイトあたりのビット数は規定されていない。sizeof(char) == 1
すなわちchar
型が1バイトであることは常に保証されるが、8ビット(オクテット)とは限らない。実際のビット数はCHAR_BIT
マクロ定数で取得できる。とはいえ、現実の多くの処理系ではchar
型は8ビットである。また、その他の整数型については、sizeof(int) >= 2
、sizeof(int) >= sizeof(short)
、sizeof(long) >= sizeof(int)
、という大小関係が定められているだけである(符号無し型も同様)。多くの処理系ではshort
型のサイズは2バイト(16ビット)であるが、int
やlong
のサイズはCPUのレジスタ幅などによって決められることが多い。int
型、short
型、long
型で符号を明示しない場合はsigned
を付けた符号付き型として扱われる。しかしchar
型に関しては、signed
(符号付き)にするか、それともunsigned
(符号無し)にするかは処理系依存である。char
型、signed char
型、unsigned char
型はそれぞれ異なる型として扱われる。
規格上には、BCPLやC++形式の1行コメント(//…
)は無いが、オプションで対応した処理系も多く、gccやClangはGNU拡張-std=gnu89
でサポートしている。
GNU Cコンパイラ や Clang では、-std=c89
(または-ansi
もしくは-std=c90
)をつけることにより、GNU拡張を使わないC89規格に準拠したコンパイルを行うことができる。加えて、-pedantic
をつければ診断結果が出る。商用のコンパイラではWatcom Cコンパイラが規格適合の比率が高いと言われていた。現在Open Watcomとして公開している。
C89には、下記の追加の訂正と追加を行った。
1999年12月1日に、ISO/IEC JTC1 SC22 WG14 で規格の改訂を行い、C++の機能のいくつかを取り込むことを含め機能を拡張し、ISO/IEC 9899:1999(E) Programming Language--C (Second Edition) を制定した。この版のC言語の規格を、通称としてC99と呼ぶ。
日本では、日本産業規格 JIS X 3010:2003「プログラム言語C」がある。
主な追加機能:
_Bool
型が予約語に追加され、標準ライブラリとしてstdbool.h
を追加した。_Complex
型や_Imaginary
型を予約語に追加し、標準ライブラリとして、complex.h
を追加した。long long int
型の追加。stdint.h
)。//
による1行コメント。inline
キーワード)。alloca
関数の代替)。C99は下記の訂正がある。
2011年12月8日にISO/IEC 9899:2011(通称 C11)として改訂された。
C11はUnicode文字列(UTF-32、UTF-16、UTF-8の各符号化方式)に標準で対応している。そのほか、type-generic
式、C++と同様の無名構造体・無名共用体、排他的アクセスによるファイルオープン方法、quick_exitなどのいくつかの標準関数などを追加した。
また、_Noreturn
関数指示子を追加した。_Noreturn
は従来処理系ごとに独自に付加していた属性情報(たとえばgccでは__attribute__((__noreturn__))
)を標準化したもので、「呼び出し元に戻ることがない」という特殊な関数についてその特性を示すためにある。return
文を持たない関数という意味ではなく(規格ではreturn
文を持たなくとも、関数の最後の文の実行が終われば制御は呼び出し元に戻る)、_exit
やexecve
を実行したり、例外、longjmp
による大域ジャンプなどのために、制御が呼び出し元に戻らないことを明示するためにある。そのような関数は、スタックに戻りアドレスを積む通常の呼び出しではなく、スタックを消費しないジャンプによって実行できる。
C11規格では一部の機能を省略可能とした。すなわちコンパイラがC11に合致していても、一部機能は提供しないことがある。コンパイラがどの機能を提供しているかは、テスト用のマクロで判別できる。アラインメント機能や_Atomic
型、C言語ネイティブの原始的なスレッド機能などが、C11では省略可能な機能として追加された。また、複素数型と可変長配列はC99では必須機能であったが、C11では省略可能である。
gets
関数が廃止された。
2018年にISO/IEC 9899:2018(通称C17またはC18)として改訂された。仕様の欠陥修正がメインのマイナーアップデートである。
大抵の処理系はC言語とC++両方をサポートしている。C言語とC++の共通部分を明確にし、二つの言語の違いに矛盾が生じないようにすることが課題になっている。
その他にも、OpenGLシェーダー言語であるGLSL、DirectX(Direct3D)シェーダー言語であるHLSL、OpenCLカーネル記述言語であるOpenCL-Cなど、C言語の文法的特徴を取り入れた派生言語やDSLが多数存在する。
2015年現在、初心者向けのイラスト入り入門書やサブルーチンのサンプル集の他、組み込み機器の制御や科学技術計算など目的を特化した専門書なども多数ある。便利な機能の説明はあっても、学習者の水準や目的にあった本を見つけるのは必ずしも容易でない。オープンソースのCコンパイラ、OSも大規模なものがあり、直接読み始めるのは困難になっている。オープンソースのOSの小規模なものから始めるとよい。
This article uses material from the Wikipedia 日本語 article C言語, which is released under the Creative Commons Attribution-ShareAlike 3.0 license ("CC BY-SA 3.0"); additional terms may apply (view authors). コンテンツは、特に記載されていない限り、CC BY-SA 4.0のもとで利用可能です。 Images, videos and audio are available under their respective licenses.
®Wikipedia is a registered trademark of the Wiki Foundation, Inc. Wiki 日本語 (DUHOCTRUNGQUOC.VN) is an independent company and has no affiliation with Wiki Foundation.