C言語 (しーげんご)は、1972年 にAT&Tベル研究所 のデニス・リッチー (Dennis M. Ritchie) が主体となって作ったプログラミング言語 である。英語圏では単に C と呼称されており、日本でも著作によっては C と記述される。
UNIX の移植性を高めるために開発された経緯から、オペレーティングシステム カーネル 向けの低レベルな記述ができることを特徴としており、移植用アセンブラ と呼ばれることもある。
特徴
Cは手続き型言語 であり、コンパイラ言語 として設計された。Cは、自由度、実行速度、コンパイル速度などを追求したが、代わりにコンパイル後のコードの安全性を犠牲にもしているので、コンピュータ寄りの言語仕様になっている。
アマチュアからプロのエンジニアまで、非常にプログラマ人口が多い。Cは正負の両面含めてコンピュータの世界に大きな影響を及ぼしているが、最大の原因はそのプログラマ人口の多さであると言われている。
パソコンはもちろんのこと、組込み用マイコンから大型コンピュータまで、Cを使用できるプラットホームが多様である。また、仕様規格・派生言語も多い。
採用されているソフトウェア分野が広い。極論すれば、Cの採用が最適である分野は一つもなく各々の分野に特化した言語に劣ると言える。しかし、あらゆる分野に対してある程度の言語適性があり現実的な選択肢としてよく用いられる。発祥の地であるUNIXの場合、大抵のことがスクリプト言語 ・マクロプロセッサ やフィルタ で処理できるため、Cを使うのはある意味最後の手段であって、うまく分野の棲み分けができていた面があるのだが、幅広い領域に移植された結果、適切でない分野にCが使われている場面もある。
低水準な記述が出来る高級言語とも、高級言語の顔をした低級言語とも言われる。また、コーディング上の“自由度”が非常に高い。そのため良くも悪くも“何でも出来てしまう”パワフルさは多くのプログラマの支持を集める一方で、単なる無秩序無分別な下品さと揶揄されることもありセキュリティー脆弱性や潜んだバグによる想定外の動作、コンパイラによる最適化の難しさ(そのためCはコンパイラ言語として決して高速ではない)といった欠点の原因ともなっている。
商用・非商用を問わずコンパイラやC向けのエディタが豊富で開発環境が整備しやすい。
Cの主な特徴は以下の通りである(歴史的な経緯から
BASIC や
Pascal と比較されることが多い)。
自由度
行番号 を採用せず文の区切りを区切り記号 ; セミコロン で表し、改行文字 にも空白 にもトークン の区切りとしての意味しか持たせない「フリーフォーマット 」という形式を採用している。
*記述作法について、しばしば議論の対象となり、本も多数出版されている。
*IOCCC のような試みはCの柔軟性を負の方向に追求し、難解性を昇華させた一種のアートといえる。
ALGOL の思想を受け継いで構造化 をサポートしており、手順を入れ子 構造で示して見通しの良い記述をすることができる。原理的に無条件分岐 (goto文 )を使用する必要が軽減されるため、スパゲティプログラム と呼ばれるような読みにくいプログラムになりにくい。
モジュール化 がファイル を単位として可能。モジュール内だけで有効な名前を使うことが出来る。(スコープ )
プログラムを関数 (戻り値 つきのサブルーチン )に分離できる。関数の中では独立した変数が使用でき、データの流れがブロックごとに完結しデバッグが容易になる。また、多人数での共同開発の際にも変数名の衝突が回避できる(これらもCで始まったアイデアではない)。なおCではメインルーチンも関数の一つ(main関数)となっているため、プログラム中で再帰的にmain関数を呼ぶことも可能。(C++では不可能)
OS記述言語として設計されたため、高級言語であるがアセンブラ 的な低レベルの操作ができる。ポインタ 演算 、ビットごとの論理演算 、シフト演算 などの機能を持ち、ハードウェア に密着した処理を効率よく記述できる。これはOSやドライバ などを記述する上では便利であるが、注意深く利用しないと発見しにくいバグ の原因となる。(このため、後継言語にはポインタ演算の機能を省いているものもある)
配列とポインタの宣言は別物であるが、配列操作の実体はポインタ演算である。
*ポインタを配列表記でアクセスすることや、配列をポインタ表記でアクセスすることができる。(糖衣構文 と呼ばれる)
アセンブラとのインターフェース
多くの処理系がインラインアセンブラを搭載しているほか、アセンブラで出力したオブジェクトとのリンクが容易になっている。これにより速度が要求される部分だけをアセンブリ言語 で記述するということが容易に行えることが多い。もっとも、アセンブラとのインターフェースに統一された仕様はなくCPUやOSなどが同一であっても移植性は低い。
RISC CPUには、アセンブラでの記述が難しく、Cでの記述を前提とするものも多い。
コンパイラ仕様
コンパイラの処理が1パスで済む仕様になっている。具体的には、変数 はその使用より前に宣言をする必要があり、関数 は宣言がないとint型が適用されるなど。(後継言語では記述によって先読みが必要になりうる)
標準でマクロ記述やコンパイル条件の指定が出来るプリプロセッサ を持ち(C Preprocessor )、その名の通りコンパイラの処理の前に実行される。
処理系の簡素化
現在のPCではこれらの脆弱性対策を施しても実行速度の低下は殆どの場合において無視できる程度であるため、そのような環境でCを使う者からは欠点・不要などと言われることが多い。
配列 参照時の自動的な添字のチェックをしない
この要因の代表的なバグがバッファオーバーフロー である。標準ライブラリにはバッファオーバーフローを考慮していない関数があり、かつ多用されがちなため、しばしば脆弱性 の原因となる。
文字列 を格納するための特別な型が存在しない
文字列にはchar型の配列やポインタを利用する。言語仕様上に特別な扱いはないが、ナル文字(ヌル 文字、'\0')を終端とする文字列 表現を使い、その操作をする標準ライブラリ 関数が提供されている。これは実質的にメモリ領域のポインタアクセスそのもので、バッファオーバーラン の元凶の一つとなっている。後継言語では文字列処理が特に強化されている場合が多い。
自動変数の自動的な初期化をしない
自動変数(静的でないローカル変数)は変数の中でも最も頻繁に用いられる。初期化しない変数の初期値は不定(その変数のアドレスに元から入っていた値)である。変数宣言・初期化の仕様による制限から、変数宣言の時点で初期化せず後で代入することで初期化に代えることが日常的で、誤って不定の値の変数を読み出すバグ を作り込みやすい。なお自動変数の自動とはスタック 上に自動的に変数の領域が確保されるという意味であり、自動的な初期化の自動とは異なる意味である。
その他
文字の大文字・小文字が区別される。
入出力 を含め、実行時の言語独自のランタイムシステム の存在をほとんど期待しない。ほとんどの機能をC自身で書かれたライブラリ が提供する。すなわち、I/O関係は言語の外にある。このことは、Cが機種依存性が低い、I/O関係ライブラリをのぞいた部分は移植性 (ポータビリティ)が高いことを意味する。さまざまな機種があるUNIXの世界でCが普及した理由の一つである。
プログラムの実行に必要とするハードウェア 資源が、(アセンブラよりは多いが)他の高級言語より少なくてすむため、現在さまざまな電化製品等の組み込みシステム にも使用されている。
コード例
Hello world プログラム
CのHello worldプログラムには、入門書によって趣が異なるいくらかのバリエーションが存在する。Cライブラリのprintf関数を利用したものが最も一般的で、以下のようなものである。
#include
int main(void)
{
printf("Hello, World!\n");
return 0;
}
なお、printf関数は変数や書式化された文字列などが表示できる比較的高機能な出力関数であり、Hello worldプログラムにはオーバースペック であると言える。Cライブラリには固定文を表示するためのputs関数が用意されており、これを用いる入門書もある。
#include
int main(void)
{
puts("Hello, World!");
return 0;
}
また、Cの仕様から言えば、puts関数に渡している引数は文字列ではなく文字列へのポインタである。よって、入門者にとって難関と言われるポインタを早くから理解させるために、Hello Worldプログラムからポインタを使ったコードを例示する入門書もある。
#include
int main(void)
{
char *str = "Hello, World!";
puts(str);
return 0;
}
さらには、文字列をchar型へのポインタではなく配列として扱うことを好み、以下のようなコードを例示する入門書もある。
#include
int main(void)
{
char str[] = "Hello, World!";
puts(str);
return 0;
}
このように、入門書によって多様なHello World!プログラムが見られるのも、自由度の高いCならではの現象といえよう。
主な制御構造
主な標準ライブラリ関数
歴史
誕生
Cは、AT&Tベル研究所のケン・トンプソン (Ken Thompson) が開発したB言語 を改良して作られた。
1973年 、トンプソンとUNIX の開発を行っていたデニス・リッチー (Dennis MacAlistair Ritchie) はBを改良し、実行可能な機械語 を直接生成するCコンパイラ を開発した。UNIXは大部分がCによって書換えられ、その後にCは広く利用されるようになった。
UNIX環境とC
アセンブラとの親和性が高いためにハードウェアに密着したコーディングがやりやすかったこと、言語仕様が小さいためコンパイラの開発が楽だったこと、小さな資源で動く実行プログラムを作りやすかったこと、UNIX環境での実績があり、後述のK&Rといった解説文書が存在していたことなど、さまざまな要因からCは業務開発や情報処理研究でのシェアを増やしていった。特にメーカー間でOS・CPUなどのアーキテクチャが違うUNIX環境では再移植の必要性がしばしば生じて、プログラムをCで書いて互換性 を取ることが標準となった。
パソコンの歴史とC
1980年代 にROM-BASICを搭載するパーソナルコンピュータ (パソコン)が普及してBASIC で初めてプログラミングに触れるプログラマが世界的に多数を占めるようになった。これらのパソコンの主流がROM-BASIC搭載機からMS-DOS 実行機に移った1980年代後半には、当時パソコン向けのコンパイラとしては安価な2万円前後のコンパイラが存在したことなどから、ユーザーが急増した。8ビットや8086系のパソコンへの移植は、ポインタなどに制限や拡張を加えることで解決していた。
現在のC
1990年代 中盤以降は、最初に学ぶプログラミング言語としても主流となった。GUI 環境の普及とオブジェクト指向 の普及によりC++ 、Java 、Visual Basic 、各種スクリプト言語 のシェアも増加したため、広く利用されるプログラミング言語の数は増える傾向にあるが、現在でもCは業務用開発やフリーソフトウェア 開発、C++などの実装が困難な組み込みなどの小規模のシステムで、幅広く利用されている。
Cの規格
K&R
1978年 に出版された、リッチーとカーニハン の共著である「The C Programming Language (いわゆる「K&R」)」は、その後標準化がなされるまで実質的なCのリファレンスとして使用された。しかし、「The C Programming Language 」の記述にはいくつか曖昧な部分が存在していた。そのため、Cが普及するに従い、互換性のない処理系 が数多く誕生することとなった。
C89
そこで、ISO と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 Cを特にC90と呼ぶことがあるが、内容はC89と同一である。
日本では、これを翻訳したものが日本工業規格 『JIS X3010-1993 プログラム言語C』として、1993年 10月に制定された。
最大の特徴は、C++と同様の
関数プロトタイプ を導入して引数の型チェックを強化したことと、voidやenumなどの新しい型を導入したことである。一方、「処理系に依存する」とするに留めた部分も幾つかある(int型のビット幅、char型の符号、
ビットフィールド の
エンディアン 、シフト演算の挙動、構造体などへの
パディング 、等)。
型の大きさは厳密に決められてはおらず、バイト数はsizeof 演算子で取得し、最大最小値はlimits.hで参照することとされている。もっとも、多くの処理系ではchar型は8ビット、short型は16ビット、long型は32ビットである。またAPIなどの呼び出しには、ヘッダでBYTEやWORDなどとtypedef した型を使用して回避するのが一般的になっている。char型以外で符号を明示しない場合はsignedになる。
規格上には、コメントのネストや、BCPL・C++タイプの一行コメント(//)は無いが、オプションでサポートした処理系も多い。
C95
主として英語圏での利用を想定して制定されたC89に対して、主に国際化のためワイド文字 版ライブラリを追加したAmendment1が1995年 に発行された。
C99
1999年 12月には、ISOで規格の改定が行われ、C++ の機能のいくつかを取り込むことを含めた機能拡張がなされ INTERNATIONAL STANDARD ISO/IEC 9899 : 1999(E) Programmin Language-C (Second Edition) が制定された。この版のCの標準規格を通称としてC99 と呼ぶ。
日本では、日本工業規格版として『JIS X 3010-2003 プログラム言語C』がある。
MISRA-C
正式名称は“Guidelines for the Use of the C Language in Vehicle Based Software”。欧州の自動車業界団体MISRA (Motor Industry Software Reliability Association)によって発表された、車載用ソフトウェアを対象としたCによるコーディングガイドライン。
日本では、(社)自動車技術会より、テクニカルペーパーTP-01002「自動車用C言語利用のガイドライン」として発行されている。
主なC処理系
現在はC/C++兼用となっている処理系が多い。
x86系のみ対応するもの
MS-C
Microsoft Visual C++ の前身。
Quick-C
MS-Cの廉価版 の位置づけ。
Borland C , Turbo C
コンパイルが速い。
Digital Mars C
Lattice C を起源とするx86用のC/C++コンパイラで、フリーソフト版もある。
Watcom C
PC/AT互換機 用。
Intel Compiler
Intel社が配布しているコンパイラ。gcc 互換。
x86系以外に対応するもの
GNUコンパイラコレクション (GCC)
多様なCPUに対応する。
CodeWarrior
Macintosh 、家庭用ゲーム機 など。
LSI C
8080 ・Z80 用のLSI C-80(セルフ版・クロス版。現在はクロス版のみ)と、8086 用のLSI C-86 がある。8086では機能限定(スモールモデル のプログラムしか開発できず、デバッガ がない)の「試食版」がフリーソフト で公開され、広く使われた。試食版は『C MAGAZINE 』(2006年4月号で休刊)の付録フロッピーディスク やCD-ROM にも収録されていた。
High C
元はx86向けでPC/AT互換機 用だが80386 のネイティブモードに対応したためFM TOWNS でも標準開発環境として使用された。現在は各社RISC 向け。
Hitech-C
Z80 、PIC など。
IAR-C
新旧の組み込み向けCPU各種を広くカバーする。現在は統合開発環境EW・SWに移行。
C compiler PRO68K
X68000 。通称XC。X-BASICをコンパイルすることも可能だった。
BDS-C
CP/M (8080・Z80)用。
関連するプログラミング言語
先祖
BCPL
MULTICS で作成された高級言語。
B言語
初期のUNIXで作成されたインタプリタ方式の高級言語。BCPLを元に作られ、Cの原型となった。
拡張
C++
Cを拡張してオブジェクト指向 化したもの。現在は互換性は失われている。
Objective-C
Cを拡張してオブジェクト指向化したもの。CにSmalltalk のオブジェクトシステムを取り付けたような設計で、互換性は保たれている。Cからの拡張部分がC++と干渉しないため、C++と混在した記述が可能。
Cg
CをGPU でのグラフィック処理用に特化させたもの。
SystemC
Cをハードウェア記述言語 に特化させたもの。
関連
Pascal
教育向けの構造化言語の一つで、Cより先行して普及した。
Java
仮想機械 方式のオブジェクト指向言語。
後継
C#
仮想機械方式のオブジェクト指向言語。C・C++との互換性はない。
D言語
Cの後継を目指している言語の一つ。C・C++との互換性はない。
その他
サーティファイが実施しているC言語プログラミング能力認定試験 がある。
参考文献
プログラミング言語C; Brian Kernighan、Dennis M. Ritchie著; 石田晴久 訳 第2版; ISBN 4-320-02692-6; 共立出版株式会社 1994.
K&R として知られているThe C Programming Language の邦訳。C の入門書。
外部リンク
ISO
The ; Dennis M. Ritchie著 - プログラミング言語Cがどのように開発されたかがわかる文書
bug:C (basa maprogram)