The Development of the C Language*

Dennis M. Ritchie
Bell Labs/Lucent Technologies
Murray Hill, NJ 07974 USA


dmr@bell-labs.com

ABSTRACT
アブストラクト

The C programming language was devised in the early 1970s as a system implementation language for the nascent Unix operating system. Derived from the typeless language BCPL, it evolved a type structure; created on a tiny machine as a tool to improve a meager programming environment, it has become one of the dominant languages of today. This paper studies its evolution.
Cプログラミング言語は、1970年代の初めに 初期の Unix オペレーティング・システムの システム・インプリメンテーション言語として考案されました。 タイプレスの言語だった BCPL から派生して、 型構造を発展させました。 貧弱なプログラミング環境を改善するツールとして、 小さなマシン上で作成されたものですが、 今日、主要な言語のうちの1つになりました。 この論文はその発展を研究します。

Introduction
イントロダクション

NOTE: *Copyright 1993 Association for Computing Machinery, Inc. This electronic reprint made available by the author as a courtesy. For further publication rights contact ACM or the author. This article was presented at Second History of Programming Languages conference, Cambridge, Mass., April, 1993.

This paper is about the development of the C programming language, the influences on it, and the conditions under which it was created. For the sake of brevity, I omit full descriptions of C itself, its parent B [Johnson 73] and its grandparent BCPL [Richards 79], and instead concentrate on characteristic elements of each language and how they evolved.
この論文は、 Cプログラミング言語の開発、 それに対する影響、 およびそれが作成された条件について述べます。 簡潔さのために、私は C、 その親の B [Johnson 73]、 およびその祖父の BCPL [Richards 79] 自体の詳細な記述を省略し、 その代り各言語の特有の要素、 およびそれらはどのように発展したかに専念します。

C came into being in the years 1969-1973, in parallel with the early development of the Unix operating system; the most creative period occurred during 1972. Another spate of changes peaked between 1977 and 1979, when portability of the Unix system was being demonstrated. In the middle of this second period, the first widely available description of the language appeared: The C Programming Language, often called the `white book' or `K&R' [Kernighan 78]. Finally, in the middle 1980s, the language was officially standardized by the ANSI X3J11 committee, which made further changes. Until the early 1980s, although compilers existed for a variety of machine architectures and operating systems, the language was almost exclusively associated with Unix; more recently, its use has spread much more widely, and today it is among the languages most commonly used throughout the computer industry.
Cは Unix オペレーティング・システムの初期の開発と平行して 1969-1973年 に実装されましたが、 最も頻繁に改変された期間は 1972 年でした。 また1977年と1979年の間の Unix システムの ポータビリティが検証されていた時にも、 多くの修正が施され改変のピークに達しました。 この第2の期間の中頃に、 言語の第1の広く利用可能な書籍 The C Programming Language が現われました。 それはしばしば `white book' あるいは `K&R' [Kernighan 78] と呼ばれました。 最後に 1980 年代の半ばに、 言語は ANSI X3J11 委員会によって さらに変更を加えた上で 公式に標準化されました。 1980年代の初めまで、 コンパイラーは様々なマシン・アーキテクチャー およびオペレーティング・システム用に存在しましたが、 言語はほとんど排他的に Unix に関係していました。 しかし最近では、その使用は非常に多岐に広がりました。 また今日、それはコンピューター産業の全体にわたって、 最も一般に使用される言語であります。

History: the setting
歴史:セッティング

The late 1960s were a turbulent era for computer systems research at Bell Telephone Laboratories [Ritchie 78] [Ritchie 84]. The company was pulling out of the Multics project [Organick 75], which had started as a joint venture of MIT, General Electric, and Bell Labs; by 1969, Bell Labs management, and even the researchers, came to believe that the promises of Multics could be fulfilled only too late and too expensively. Even before the GE-645 Multics machine was removed from the premises, an informal group, led primarily by Ken Thompson, had begun investigating alternatives.
1960年代の終わりはベル電話研究所のコンピューター・システム研究は 騒然とした時代でした。[Ritchie 78] [Ritchie 84] 会社は Multics プロジェクト [Organick 75] から撤退しつつありました。 Multics プロジェクトは MIT、ゼネラル・エレクトリック、 ベル研究所のジョイント・ベンチャとしてスタートしたプロジェクトで、 1969 年にはベル研究所の管理者だけでなく研究者でさえ、 Multics の約束が達成できるものは遅すぎる、 高価すぎるものだけであることを信じるに至っていました。 研究所から Multics マシンである GE-645 が撤去されるそれ以前から、 Ken Thompson の率いる非公式のグループは代案を調査し始めました。

Thompson wanted to create a comfortable computing environment constructed according to his own design, using whatever means were available. His plans, it is evident in retrospect, incorporated many of the innovative aspects of Multics, including an explicit notion of a process as a locus of control, a tree-structured file system, a command interpreter as user-level program, simple representation of text files, and generalized access to devices. They excluded others, such as unified access to memory and to files. At the start, moreover, he and the rest of us deferred another pioneering (though not original) element of Multics, namely writing almost exclusively in a higher-level language. PL/I, the implementation language of Multics, was not much to our tastes, but we were also using other languages, including BCPL, and we regretted losing the advantages of writing programs in a language above the level of assembler, such as ease of writing and clarity of understanding. At the time we did not put much weight on portability; interest in this arose later.
Thompson は利用可能だったあらゆる手段を利用して、 自分の設計によって構築された快適な計算する環境を築きたかったようです。 振り返ってみると明白ですが、 彼の計画は 1つのコントロールの軌跡としてのプロセスについての明示的な概念、 木構造のファイル・システム、 ユーザー・レベル・プログラムとしてのコマンド・インタープリタ、 テキストファイルの単純な表現、 一般化されたデバイスへのアクセスなどを含む、 数多くの multics の革新的な特徴を盛り込んでました。 メモリやファイルへの統一されたアクセスのように、 他のものを除外しました。 さらに当初、 彼と残りの私たちは Multics の先駆的な(でもオリジナルではない) その他のエレメントを保留しました。 すなわち高水準言語を書くことに集中したのです。 Multics の実装用言語だった PL/I は それほど私たちの好みではありませんでしたので、 BCPL を含むその他の言語も使用していました。 また私たちは、 記述の容易さや理解の明瞭のような、 アセンブラのレベル以上の言語で書くプログラムの利点を 失うことを残念に思っていました。 その時点で、 私たちはポータビリティにはあまり重きを置きませんでしたが、 その後これへの関心は起こりました。

Thompson was faced with a hardware environment cramped and spartan even for the time: the DEC PDP-7 on which he started in 1968 was a machine with 8K 18-bit words of memory and no software useful to him. While wanting to use a higher-level language, he wrote the original Unix system in PDP-7 assembler. At the start, he did not even program on the PDP-7 itself, but instead used a set of macros for the GEMAP assembler on a GE-635 machine. A postprocessor generated a paper tape readable by the PDP-7.
Thompson はその時点でさえ質素で窮屈なハードウェア環境に直面しました: 彼が 1968 年に取りかかった DEC PDP-7 は 18 ビット・ワードの 8K メモリを備えた、 彼にとって有用なソフトウェアはない機械でした。 高水準言語の使用を望んでいた頃、 彼は PDP-7 アセンブラでオリジナルの Unix システムを書きました。 最初は彼は PDP-7 の上でプログラムすることはなく、 その代りに GE-635 マシン上で GEMAP アセンブラ用の一組ののマクロを使用しました。 ポストプロセッサで PDP-7 が判読可能な紙テープを生成しました。

These tapes were carried from the GE machine to the PDP-7 for testing until a primitive Unix kernel, an editor, an assembler, a simple shell (command interpreter), and a few utilities (like the Unix rm, cat, cp commands) were completed. After this point, the operating system was self-supporting: programs could be written and tested without resort to paper tape, and development continued on the PDP-7 itself.
これらのテープは 原始的な Unix カーネル、エディタ、アセンブラ、 シンプルなシェル(コマンド・インタープリタ)、 および (Unix の rm, cat, cp コマンドのような) 少数のユーティリティが完成するまで、 テストのために GE マシンから PDP-7 へ 運ばれました。 この時点以降、 オペレーティング・システムはセルフ・サポートになりました: 紙テープの助けを借りることなく、 プログラムを書き、テストすることが出来るようになりました。 そして開発は PDP-7 上で続けられました。

Thompson's PDP-7 assembler outdid even DEC's in simplicity; it evaluated expressions and emitted the corresponding bits. There were no libraries, no loader or link editor: the entire source of a program was presented to the assembler, and the output file - with a fixed name - that emerged was directly executable. (This name, a.out, explains a bit of Unix etymology; it is the output of the assembler. Even after the system gained a linker and a means of specifying another name explicitly, it was retained as the default executable result of a compilation.)
Thompson の PDP-7 アセンブラの単純さは DEC のものさえ凌駕しました; それは式を評価し、対応するビットを立てものでした。 ライブラリやローダーあるいはリンク・エディターもありませんでした: プログラムの全てのソースはアセンブラに与えられ、 ファイルに出力され - 名前が決められ - その生成物は直接実行できました。 (a.outという、 この名前は Unix の語源について少し説明します; それはアセンブラの出力です。 システムがリンカーを手に入れ、 明示的に他の名前を指定できるようになった後でさえも、 それはデフォルトの実行可能なコンパイル結果として残されました)

Not long after Unix first ran on the PDP-7, in 1969, Doug McIlroy created the new system's first higher-level language: an implementation of McClure's TMG [McClure 65] . TMG is a language for writing compilers (more generally, TransMoGrifiers) in a top-down, recursive-descent style that combines context-free syntax notation with procedural elements. McIlroy and Bob Morris had used TMG to write the early PL/I compiler for Multics.
PDP-7 の上で Unix が最初に走ったことの後まもなく、 1969 年には Doug McIlroy は新しいシステムの 最初の高水準言語 McClure の TMG [McClure 65] の実装を作成しました: TMG はトップ・ダウン型で、 手続き的な要素と文脈自由のシンタックス記法を組み合わせた 再帰的な継承スタイルの、 コンパイラーを書くための言語です。(より一般には TransMoGrifiers) McIlroy と Bob Morris は Multics のための early PL/I コンパイラーを書くために TMG を使用しました。

Challenged by McIlroy's feat in reproducing TMG, Thompson decided that Unix—possibly it had not even been named yet—needed a system programming language. After a rapidly scuttled attempt at Fortran, he created instead a language of his own, which he called B. B can be thought of as C without types; more accurately, it is BCPL squeezed into 8K bytes of memory and filtered through Thompson's brain. Its name most probably represents a contraction of BCPL, though an alternate theory holds that it derives from Bon [Thompson 69], an unrelated language created by Thompson during the Multics days. Bon in turn was named either after his wife Bonnie, or (according to an encyclopedia quotation in its manual), after a religion whose rituals involve the murmuring of magic formulas.
TMG の再現という McIlroy の功績を受けて、 Thompson は Unix — おそらくまだ名前はなかったはずですが — にはシステム・プログラミング言語が必要であることを決心しました。 すぐに自滅してしまった Fortran の試みの後、 代わりに彼が B と呼ぶ彼自身の言語を作成しました。 B はタイプのない C と見なすことができます; より正確には、 それはメモリの 8K バイトに押し込まれ、 Thompson の脳によってフィルターされた BCPL です。 Bon [Thompson 69] (Multics の時期に Thompson によって作成された全く無関係な言語) に由来するという異説も考えられますが、 その名前はほぼ間違いなく BCPL の短縮を表わすのでしょう。 Bon もまた彼の妻の名前 Bonnie か、 魔法の呪文のささやきを必要とする信仰の宗教 にちなんで名付けられました。

Origins: the languages
起源:言語

BCPL was designed by Martin Richards in the mid-1960s while he was visiting MIT, and was used during the early 1970s for several interesting projects, among them the OS6 operating system at Oxford [Stoy 72], and parts of the seminal Alto work at Xerox PARC [Thacker 79]. We became familiar with it because the MIT CTSS system [Corbato 62] on which Richards worked was used for Multics development. The original BCPL compiler was transported both to Multics and to the GE-635 GECOS system by Rudd Canaday and others at Bell Labs [Canaday 69]; during the final throes of Multics's life at Bell Labs and immediately after, it was the language of choice among the group of people who would later become involved with Unix.
BCPL は Martin Richards によって 1960 年代中頃、 彼が MIT のビジターだった頃に設計され、 1970 年代の初頭の間に Oxford の OS6 オペレーティング・システム [Stoy 72] や 独創性に富んだ Xerox PARC の Alto [Thacker 79] の開発の一部など いくつかの興味深いプロジェクトで使われました。 Richards が作業をした MIT CTSS system [Corbato 62] を Multics 開発のために使用していた関係で、 私たちはそれに精通しました。 オリジナルの BCPL コンパイラーは Rudd Canaday と他のベル研究所の人々によって Multics および GE-635 GECOS system の両方に移植されました [Canaday 69] ; この作業はベル研究所での Multics ライフの最後の断末魔の期間から その直後まで続き、 後に Unix に熱中するようになる人々の集団が共に選択した言語でした。

BCPL, B, and C all fit firmly in the traditional procedural family typified by Fortran and Algol 60. They are particularly oriented towards system programming, are small and compactly described, and are amenable to translation by simple compilers. They are `close to the machine' in that the abstractions they introduce are readily grounded in the concrete data types and operations supplied by conventional computers, and they rely on library routines for input-output and other interactions with an operating system. With less success, they also use library procedures to specify interesting control constructs such as coroutines and procedure closures. At the same time, their abstractions lie at a sufficiently high level that, with care, portability between machines can be achieved.
BCPL、B および C はいずれも明らかに Fortran や Algol60 によって代表される 従来の手続き型言語の範疇に入りますが、 特にシステムプログラミングの領域を指向し、 小さく、簡潔に記述されます。 そして単純なコンパイラーで素直にコード変換する事ができます。 従来のコンピューターによって提供される 具体的なデータタイプやオペレーションに立脚した 抽象的概念を導入していることから 'マシンに近い' と言えます。 また、オペレーティングシステムを介した 入出力や他の相互作用はライブラリールーチンに依存します。 With less success で、 coroutines や procedure closures のような 対象となる制御構造を定義するためにも ライブラリーのプロシージャを使用します。 同時に、この抽象的概念は 達成されるマシン間のポータビリティから 十分高水準であると言えます。

BCPL, B and C differ syntactically in many details, but broadly they are similar. Programs consist of a sequence of global declarations and function (procedure) declarations. Procedures can be nested in BCPL, but may not refer to non-static objects defined in containing procedures. B and C avoid this restriction by imposing a more severe one: no nested procedures at all. Each of the languages (except for earliest versions of B) recognizes separate compilation, and provides a means for including text from named files.
BCPL、BおよびCは、多くの詳細において構文上異なります。しかし、広く、それらは類似しています。プログラムは、世界的な宣言および関数(手続き)宣言のシーケンスから成ります。手続きはBCPLの中で入れ子にすることができるが、手続きを含んでいることの中で定義された静止でないオブジェクトに言及してはなりません。BとCはより多くの厳しいものを課することによりこの制限を回避します:すべての入れ子の手続きはありません。言語(Bの最も初期のバージョンを除いて)の各々は認識します。個別の編集、またテキストを含んでいるための手段を提供する、から、ファイルと命名されました。

Several syntactic and lexical mechanisms of BCPL are more elegant and regular than those of B and C. For example, BCPL's procedure and data declarations have a more uniform structure, and it supplies a more complete set of looping constructs. Although BCPL programs are notionally supplied from an undelimited stream of characters, clever rules allow most semicolons to be elided after statements that end on a line boundary. B and C omit this convenience, and end most statements with semicolons. In spite of the differences, most of the statements and operators of BCPL map directly into corresponding B and C.
BCPLのいくつかの構文的と語いのメカニズムは、BとCのものより上品でより規則的です。例えば、BCPLの手続きおよびデータ宣言はより一定の構造を持っています、また、それは、ループするより多くの完全なセットを供給します、構築します。BCPLプログラムは文字の限界を定められていない流れから概念的に供給されますが、利口な規則はライン境界で終わるステートメントの後にほとんどのセミコロンの発音が省かれることを可能にします。BとCはこの便宜を省略し、セミコロンを備えたほとんどのステートメントを終了します。違いにもかかわらず、BCPLのほとんどのステートメントおよびオペレーターは、対応するBおよびCへ直接写像します。

Some of the structural differences between BCPL and B stemmed from limitations on intermediate memory. For example, BCPL declarations may take the form
BCPLとBの間の構造の差のうちのいくつかは中間のメモリに対する制限から生じました。例えば、BCPL宣言は形式をとるかもしれません。

let P1 be command
and P2 be command
and P3 be command
 ...
where the program text represented by the commands contains whole procedures. The subdeclarations connected by and occur simultaneously, so the name P3 is known inside procedure P1. Similarly, BCPL can package a group of declarations and statements into an expression that yields a value, for example
ここでコマンドによって表わされるプログラム・テキストは全体の手続きを含んでいます。サブ宣言接続され。同時に生じる、したがって、名前 P3既知の内部の手続きP1です。例えば、同様に、BCPLは、値を産出する表現へ1グループの宣言およびステートメントをパッケージにすることができます。
E1 := valof $( declarations ; commands ; resultis E2 $) + 1
The BCPL compiler readily handled such constructs by storing and analyzing a parsed representation of the entire program in memory before producing output. Storage limitations on the B compiler demanded a one-pass technique in which output was generated as soon as possible, and the syntactic redesign that made this possible was carried forward into C.
BCPLコンパイラーは容易にそのようなものを扱いました、構築する、出力を生産する前にメモリ中の全プログラムの解析された表現を格納し分析することによって。Bコンパイラーに対する記憶制限は、出力ができるだけ早く生成された、1-パス技術を要求しました。また、これを可能にした構文的なデザイン変更はCへ前に運ばれました。

Certain less pleasant aspects of BCPL owed to its own technological problems and were consciously avoided in the design of B. For example, BCPL uses a `global vector' mechanism for communicating between separately compiled programs. In this scheme, the programmer explicitly associates the name of each externally visible procedure and data object with a numeric offset in the global vector; the linkage is accomplished in the compiled code by using these numeric offsets. B evaded this inconvenience initially by insisting that the entire program be presented all at once to the compiler. Later implementations of B, and all those of C, use a conventional linker to resolve external names occurring in files compiled separately, instead of placing the burden of assigning offsets on the programmer.
BCPLのあるそれほど楽しくない様相はそれ自身の技術的な問題に借りがあり、Bのデザインの中で意識的に回避されました。例えば、BCPLは別々にコンパイルされたプログラム間に通信するために「グローバルベクトル」メカニズムを使用します。このスキームでは、プログラマが、明示的にグローバルベクトルの中で数値のオフセットに個々の外部的に目に見える手続きおよびデータ・オブジェクトの名前を関連させます;リンケージはこれらの数値オフセットの使用によりコンパイルされたコードの中で遂行されます。Bは、全プログラムがコンパイラーに突然提示されるべきであると主張することにより、この不便を最初に回避しました。Bの後のインプリメン?eーションおよびCのすべてのもの、ファイルに生じる外部名前がコンパイルしたと決心するためにプログラマのオフセットを割り当てる負担を置く代わりに、従来の結合物を別々に使用します。

Other fiddles in the transition from BCPL to B were introduced as a matter of taste, and some remain controversial, for example the decision to use the single character = for assignment instead of :=. Similarly, B uses /**/ to enclose comments, where BCPL uses //, to ignore text up to the end of the line. The legacy of PL/I is evident here. (C++ has resurrected the BCPL comment convention.) Fortran influenced the syntax of declarations: B declarations begin with a specifier like auto or static, followed by a list of names, and C not only followed this style but ornamented it by placing its type keywords at the start of declarations.
例えば、味の問題およびいくらかが論争の的になっているままであるとともに、BCPLからBまでの推移の他のバイオリンは導入されました、単一の特徴を使用する決定 =割り当てのために、の代わりに:。同様に、Bは使用します。/**/BCPLが使用するところで、コメントを囲むこと//、ラインの終了までのテキストの無視。PL/私の遺産はここで明白です。(C++はBCPLコメント協定を生き返らせました。)フォートランは、宣言のシンタックスに影響を及ぼしました:B宣言は類似の明細書作成者から始まります。自動車あるいは静止、名前のリストおよびCによって続いた、このスタイルに続いただけでなく宣言の最初にそのタイプ・キーワードを置くことにより、それを装飾しました。

Not every difference between the BCPL language documented in Richards's book [Richards 79] and B was deliberate; we started from an earlier version of BCPL [Richards 67]. For example, the endcase that escapes from a BCPL switchon statement was not present in the language when we learned it in the 1960s, and so the overloading of the break keyword to escape from the B and C switch statement owes to divergent evolution rather than conscious change.
リチャーズの本の中でドキュメント化されたBCPL言語間の一部の違いを除く[リチャーズ79]また、Bは慎重でした;私たちは、BCPL[リチャーズ67]の初期のバージョンから出発しました。例えばendcaseそれはBCPL switchonから漏れます。私たちが1960年代にそれを学習した時、ステートメントは言語の中にありませんでした、それで破損を過負荷をかけることキーワードBおよびCスイッチから漏れることステートメント分岐することに借りがあります。意識的な変更ではなく発展。

In contrast to the pervasive syntax variation that occurred during the creation of B, the core semantic content of BCPL - its type structure and expression evaluation rules - remained intact. Both languages are typeless, or rather have a single data type, the `word,' or `cell,' a fixed-length bit pattern. Memory in these languages consists of a linear array of such cells, and the meaning of the contents of a cell depends on the operation applied. The + operator, for example, simply adds its operands using the machine's integer add instruction, and the other arithmetic operations are equally unconscious of the actual meaning of their operands. Because memory is a linear array, it is possible to interpret the value in a cell as an index in this array, and BCPL supplies an operator for this purpose. In the original language it was spelled rv, and later !, while B uses the unary *. Thus, if p is a cell containing the index of (or address of, or pointer to) another cell, *p refers to the contents of the pointed-to cell, either as a value in an expression or as the target of an assignment.
浸透しているシンタックス変化とは対照的に、それ?ヘBの生成中に生じた、BCPL - その型構造と表現評価のルール - remainedした核心、完全。両方の言語は型がないか、あるいは単一のデータ・タイプ、「単語」あるいは「セル」(固定長ビット・パタン)がややあります。これらの言語のメモリはそのようなセルのリニア・アレイから成ります。また、セルの内容の意味は、応用のオペレーションに依存します。その+オペレーターは、例えば、機械の整数を使用するそのオペランドが指示を加えると単に付け加えます。また、他の演算オペレーションは、それらのオペランドの実際の意味に等しく気づいていません。メモリがリニア・アレイであるので、この配列中のインデックスとしてセルの値を解釈することは可能です。また、BCPLはこの目的にオペレーターを供給します。オリジナルの言語では、それが綴られたrvでした、そしてその後!Bが単項のものを使用している一方* 。
したがって、場合、p セルを含むことです。別のセル、*pの(あるいはアドレス、の、あるいはポインター、に)インデックス 指示されたセルの内容を表現での値あるいは割り当ての目標のいずれかと呼んでください。

Because pointers in BCPL and B are merely integer indices in the memory array, arithmetic on them is meaningful: if p is the address of a cell, then p+1 is the address of the next cell. This convention is the basis for the semantics of arrays in both languages. When in BCPL one writes
BCPLとBの中のポインターが単にメモリ配列中の整数索引であるので、それらの上の算術は意味があります:場合pセル、その後p+1のアドレスです。次のセルのアドレスです。この協定は両方の言語の配列の意味論の根拠です。BCPLでは、人が書く場合

let V = vec 10
or in B,
あるいはBの中で、
auto V[10];
the effect is the same: a cell named V is allocated, then another group of 10 contiguous cells is set aside, and the memory index of the first of these is placed into V. By a general rule, in B the expression
結果は同じです:指定されたセルVその後割り付けられる、10個の接触するセルの別のグループはわきに置かれます、また、これらの1番めのメモリ・インデックスはVに入れられます。Bの中で、総則によって、表現
*(V+i)
adds V and i, and refers to the i-th location after V. Both BCPL and B each add special notation to sweeten such array accesses; in B an equivalent expression is
加えます。Vそしてi、またVの後にi―th位置を参照します。両方BCPLおよびBは各々、そのような配列アクセスを甘くするために特別の記法を加えます;Bでは、等価な表現がそうです。
V[i]
and in BCPL
そしてBCPLの中で
V!i
This approach to arrays was unusual even at the time; C would later assimilate it in an even less conventional way.
配列へのこのアプローチはその時にさえ異常でした;Cは、その後さらに従来でない方法でそれを同化するでしょう。

None of BCPL, B, or C supports character data strongly in the language; each treats strings much like vectors of integers and supplements general rules by a few conventions. In both BCPL and B a string literal denotes the address of a static area initialized with the characters of the string, packed into cells. In BCPL, the first packed byte contains the number of characters in the string; in B, there is no count and strings are terminated by a special character, which B spelled `*e'. This change was made partially to avoid the limitation on the length of a string caused by holding the count in an 8- or 9-bit slot, and partly because maintaining the count seemed, in our experience, less convenient than using a terminator.
BCPL、BあるいはCのどれも、言語で文字データを強く支援しません;各々は非常に整数のベクトルのようにストリングを扱い、少数の協定による総則を補足します。BCPLおよびBの両方では、ストリングのリテラルが、セルに詰められて、ストリングの特徴で初期化された静止のエリアのアドレスを表示します。BCPLでは、第1のパックされたバイトが、ストリングに文字の数を含んでいます;Bでは、計算とストリングはありません、特別の特徴によって終了する、どのB、綴られた「*e「。この変更は部分的に8-あるいは9ビットのスロットに計算を保持することにより引き起こされたストリングの長さに対する制限を回避するために行なわれました、また部分的に私たちの経験の中で、見えられた計算を維持するので、ターミネーターを使用するほど便利でない

Individual characters in a BCPL string were usually manipulated by spreading the string out into another array, one character per cell, and then repacking it later; B provided corresponding routines, but people more often used other library functions that accessed or replaced individual characters in a string.
BCPLストリング中の個々の特徴は、別の配列、1個のセル当たり1文字および、次に、それをその後詰め直すことへストリングを広げることにより通常操作されました;Bは対応するルーチンを提供しました。しかし、人々は、ストリングの中でアクセスした他のライブラリー機能あるいは交換された個人文字をよりしばしば使用しました。

More History
より多くの歴史

After the TMG version of B was working, Thompson rewrote B in itself (a bootstrapping step). During development, he continually struggled against memory limitations: each language addition inflated the compiler so it could barely fit, but each rewrite taking advantage of the feature reduced its size. For example, B introduced generalized assignment operators, using x=+y to add y to x. The notation came from Algol 68 [Wijngaarden 75] via McIlroy, who had incorporated it into his version of TMG. (In B and early C, the operator was spelled =+ instead of += ; this mistake, repaired in 1976, was induced by a seductively easy way of handling the first form in B's lexical analyzer.)
B の TMG バージョンが動作した後、 Thompson は B をそれ自身で書き直しました。 (ブートストラップ的方法) 開発中、彼はメモリの制限に奮闘し続けることになりました: 言語に何かを追加をするたびに、 それがかろうじて適合することができたとしても、 コンパイラーを膨張させ、 しかし機能の利点を残す書き直しを行なうと そのサイズを縮小しました。 例えば B は一般化された代入操作を導入しました。 xy を加えるために x=+y を使用します。 この記法は McIlroy によって Algol 68 [Wijngaarden 75] から来たものです。 彼は TMG の彼自身が作成したバージョンにそれを組み入れてました。 ( B や初期の C ではオペレーターは += ではなく =+ と綴られていました; 1976 年に修正されたこの誤りは B のレキシカル・アナライザーの中の 1番目の形式を扱う簡単な方法の誘惑によって引き起こされました。)

Thompson went a step further by inventing the ++ and -- operators, which increment or decrement; their prefix or postfix position determines whether the alteration occurs before or after noting the value of the operand. They were not in the earliest versions of B, but appeared along the way. People often guess that they were created to use the auto-increment and auto-decrement address modes provided by the DEC PDP-11 on which C and Unix first became popular. This is historically impossible, since there was no PDP-11 when B was developed. The PDP-7, however, did have a few `auto-increment' memory cells, with the property that an indirect memory reference through them incremented the cell. This feature probably suggested such operators to Thompson; the generalization to make them both prefix and postfix was his own. Indeed, the auto-increment cells were not used directly in implementation of the operators, and a stronger motivation for the innovation was probably his observation that the translation of ++x was smaller than that of x=x+1.
Thompson はインクリメント、ディクリメントを意味する ++-- の発明によって、さらに1ステップ上を行きました; オペレータのプリフィックス、 あるいはポストフィックスの位置によって、 オペランドの値の操作の前あるいは後に、 変更が生じるかどうか決めます。 それらは B の最も初期のバージョンにはなかったのですが、 途中で現われました。 多くの人がしばしば C と Unix が最初にポピュラーになった DEC PDP-11 によって提供される オート・インクリメントおよびオート・ディクリメント というアドレス・モードを使用するために、 彼らが作成されたと推測します。 B が開発されていた時期には PDP-11 はなかったので、 これは歴史上不可能です。 しかしながら PDP-7 は 間接メモリ参照がセルをインクリメントするような、 少数の「オート・インクリメント」メモリーセルを持っていました。 この機能は、恐らく Thompson にそのようなオペレーターを示唆したでしょう; しかしプリフィックスおよびポストフィックスにする一般化は彼の成果でした。 確かにオート・インクリメント・セルは、 オペレーターの実装のなかで直接使用されませんでした。 そして革新のより強い動機は恐らく ++xx=x+1. より小さくなるという 彼の観察力でした。

The B compiler on the PDP-7 did not generate machine instructions, but instead `threaded code' [Bell 72], an interpretive scheme in which the compiler's output consists of a sequence of addresses of code fragments that perform the elementary operations. The operations typically - in particular for B - act on a simple stack machine.
PDP-7 の B コンパイラーは機械語ではなく、 基本的な操作を実行するコード・フラグメントを アドレスするシーケンスから構成される コンパイラの出力を使ったインタプリター方式である `threaded code' [Bell 72]   * を生成しました。 それは単純なスタックマシンに基づく典型的なオペレーションでした。

On the PDP-7 Unix system, only a few things were written in B except B itself, because the machine was too small and too slow to do more than experiment; rewriting the operating system and the utilities wholly into B was too expensive a step to seem feasible. At some point Thompson relieved the address-space crunch by offering a `virtual B' compiler that allowed the interpreted program to occupy more than 8K bytes by paging the code and data within the interpreter, but it was too slow to be practical for the common utilities. Still, some utilities written in B appeared, including an early version of the variable-precision calculator dc familiar to Unix users [McIlroy 79]. The most ambitious enterprise I undertook was a genuine cross-compiler that translated B to GE-635 machine instructions, not threaded code. It was a small tour de force: a full B compiler, written in its own language and generating code for a 36-bit mainframe, that ran on an 18-bit machine with 4K words of user address space. This project was possible only because of the simplicity of the B language and its run-time system.
PDP-7 Unix システムでは B 自身を除き、 わずかのプログラムしか書かれませんでした。 マシンが小さく遅すぎたため、 実験以上の作業はできなかったからです。 オペレーティング・システムやユーティリィティを全て B で書き直すことは、 あまりにも高価なステップであったので実現可能には見えませんでした。 ある時点では、 Thompson が インタープリター内のコードおよびデータにページをつけることにより、 8K バイト以上のプログラムの実行(解釈)を可能にする `virtual B' コンパイラによってアドレス空間問題を取り除きましたが、 遅すぎたので実質的に共通のユーティリィティにはなりえませんでした。 それでも B で書かれたいくつかのユーティリィティ、 Unix ユーザに馴染み深い variable-precision calculator である dc [McIlroy 79] の初期のバージョンなどが登場しました。 私が試みた最も野心的な計画は threaded code ではなく B を GE-635 の機械語に変換する本物のクロス・コンパイラでした。 それはちょっとした 離れわざ でした: それ自身の言語で書かれ、 36 ビットのメインフレームのためのコードを生成して、 4K ワードのユーザ・アドレス空間を備えた 18 ビットのマシン上で走る、 完全な B コンパイラーです。 B 言語とそのランタイムシステムの単純性の故に、 このプロジェクトは可能でした。

Although we entertained occasional thoughts about implementing one of the major languages of the time like Fortran, PL/I, or Algol 68, such a project seemed hopelessly large for our resources: much simpler and smaller tools were called for. All these languages influenced our work, but it was more fun to do things on our own.
私たちは Fortran、 PL/I、 あるいは Algol 68 など その時期の主要な言語のうちの1つを実装する考えを私たちが検討したとしても、 そのようなプロジェクトは私たちの資源には絶望的に大きく見えました: はるかに単純で、より小さなツールが要求されました。 これらの言語はすべて私たちの仕事に影響を及ぼしましたが、 物事を独力で行うことはより楽しかったのです。

By 1970, the Unix project had shown enough promise that we were able to acquire the new DEC PDP-11. The processor was among the first of its line delivered by DEC, and three months passed before its disk arrived. Making B programs run on it using the threaded technique required only writing the code fragments for the operators, and a simple assembler which I coded in B; soon, dc became the first interesting program to be tested, before any operating system, on our PDP-11. Almost as rapidly, still waiting for the disk, Thompson recoded the Unix kernel and some basic commands in PDP-11 assembly language. Of the 24K bytes of memory on the machine, the earliest PDP-11 Unix system used 12K bytes for the operating system, a tiny space for user programs, and the remainder as a RAM disk. This version was only for testing, not for real work; the machine marked time by enumerating closed knight's tours on chess boards of various sizes. Once its disk appeared, we quickly migrated to it after transliterating assembly-language commands to the PDP-11 dialect, and porting those already in B.
1970 年に Unix プロジェクトは 新しい DEC PDP-11 を獲得できるであろうという十分な見込みを示しました。 プロセッサーは DEC によって配送されるラインの1番めの中にありました。 また、ディスクが到着するまでに3か月かかりました。 PDP-11 の上で threaded technique を使って実行する B プログラムの作成には オペレータのコード・フラグメントを出力することと、 私が B で書いた単純なアセンブラだけが必要でした。 まもなく、 PDP-11 の上でオペレーティングシステムの前にテストするためのプログラムとして dc が選ばれました。 まだディスクを待っているほぼ同時期に、 Thompson は Unix カーネルといくつかの基本的なコマンドを PDP-11 アセンブリ言語でコーディングしなおしました。 最も初期の PDP-11 Unix システムは オペレーティングシステムのために 12K バイト、 非常に小さな空間をユーザープログラムに、 残りは RAM ディスクとして使用しました。 このバージョンはテストのためにだけ用意されたもので、 実際の仕事には使われませんでした; マシンはいくつものサイズのチェスボードの上で 閉じた騎士巡礼問題を表示しながら待機しました。 ディスクが到着すると、 アセンブラ言語のコマンドを PDP-11 の方言に翻訳し、 それらを移しかえた後、 私たちは PDP-11 にすばやく移動しました。

By 1971, our miniature computer center was beginning to have users. We all wanted to create interesting software more easily. Using assembler was dreary enough that B, despite its performance problems, had been supplemented by a small library of useful service routines and was being used for more and more new programs. Among the more notable results of this period was Steve Johnson's first version of the yacc parser-generator [Johnson 79a].
1971 年には 私たちの小さなコンピュータセンターはユーザを持ち始めていました。 私たちは面白いソフトウェアをより簡単に作成したかったのです。 アセンブラーを使用する事は B よりも十分退屈で、 B はそのパフォーマンス問題にも関わらず、 非常に便利なサービスルーチンの小さなライブラリで補われた事から 新しいプログラムのためにますます使用されるようになりました。 この期間の特に注目すべき成果の中には、 Steve Johnson の yacc パーサージェネレータ [Johnson 79a] の最初のバージョンがありました。

The Problems of B
B の問題点

The machines on which we first used BCPL and then B were word-addressed, and these languages' single data type, the `cell,' comfortably equated with the hardware machine word. The advent of the PDP-11 exposed several inadequacies of B's semantic model. First, its character-handling mechanisms, inherited with few changes from BCPL, were clumsy: using library procedures to spread packed strings into individual cells and then repack, or to access and replace individual characters, began to feel awkward, even silly, on a byte-oriented machine.
私たちが BCPL や B を使用したマシンは ワード単位でのアドレッシングを採用していました。 また、いずれの言語も唯一のデータ・タイプである 'セル' は ハードウェアのマシンワードと一致していました。 PDP-11 の到来は B のセマンティクス・モデルに いくつかの不適当な点を明らかにしました。 第1に BCPL から継承しいくつかの変更を行なった 文字を扱うメカニズムは要領の悪いものでした: バイト指向のマシンにおいて、 パックされた文字列を個々のセルに広げて、 パックし直す、 あるいは個々の文字について参照したり置き換えたりするといった ライブラリのプロシージャを使うことは、 格好の悪い実に間の抜けた事のように感じ始めました。

Second, although the original PDP-11 did not provide for floating-point arithmetic, the manufacturer promised that it would soon be available. Floating-point operations had been added to BCPL in our Multics and GCOS compilers by defining special operators, but the mechanism was possible only because on the relevant machines, a single word was large enough to contain a floating-point number; this was not true on the 16-bit PDP-11.
第2に、 オリジナルの PDP-11 は浮動小数点演算に備えませんでしたが、 メーカーはすぐに利用可能になるだろうと約束しました。 私たちの Multics や GCOS の BCPL コンパイラでは 浮動少数点演算は特殊なオペレータを定義する事によって追加されていました。 しかし、 この方法は代入される浮動少数より マシンの1ワードが十分に大きかったから可能な仕掛けでした; この仮定は 16 ビットの PDP-11 では正しくありません。

Finally, the B and BCPL model implied overhead in dealing with pointers: the language rules, by defining a pointer as an index in an array of words, forced pointers to be represented as word indices. Each pointer reference generated a run-time scale conversion from the pointer to the byte address expected by the hardware.
最後に、 ポインターに関わる処理において B および BCPL のモデルは オーバーヘッドが発生する事を暗示していました: ポインターをワードの配列へのインデックスと定義する言語規約は ポインタにワード・インデックスを意味する事を強いました。 この定義では、個々のポインターによる参照は実行時に ポインターからハードウェアに適したバイト・アドレスへの スケール変換をしなければなりません。

For all these reasons, it seemed that a typing scheme was necessary to cope with characters and byte addressing, and to prepare for the coming floating-point hardware. Other issues, particularly type safety and interface checking, did not seem as important then as they became later.
これらのすべての理由から 文字およびバイト・アドレシングに対処し、 また次の浮動小数点式のハードウェアの準備をするため 型に関する仕組みが必要だったように見えました。 他の問題、 特に型に対する安全性およびインターフェースのチェックは その時点では重要には見えませんでした。 それが重要になったのは後のことです。

Aside from the problems with the language itself, the B compiler's threaded-code technique yielded programs so much slower than their assembly-language counterparts that we discounted the possibility of recoding the operating system or its central utilities in B.
言語自体に関する問題に加えて、 B コンパイラーの threaded-code の技術は アセンブリ言語で書かれたものに比べて プログラムを非常に遅いものにしていました。 それが私たちがオペレーティング・システム、 あるいはその中心的なユーティリティを B で書き直す可能性を引き下げていました。

In 1971 I began to extend the B language by adding a character type and also rewrote its compiler to generate PDP-11 machine instructions instead of threaded code. Thus the transition from B to C was contemporaneous with the creation of a compiler capable of producing programs fast and small enough to compete with assembly language. I called the slightly-extended language NB, for `new B.'
1971年には、 私が文字の型を加えることにより B 言語を拡張し始め、 さらに threaded code の代わりに PDP-11 の機械語を生成するために そのコンパイラーを書き直しました。 したがって B から C への移行は、 アセンブリ言語と競争するに十分なぐらい早くて小さなプログラムを生成する コンパイラの能力の開発と同時に並行して進められました。 私はそのわずかに拡張した言語を NB (新しい B)と呼びました。

Embryonic C
初期の C

NB existed so briefly that no full description of it was written. It supplied the types int and char, arrays of them, and pointers to them, declared in a style typified by
NB が存在したのは極短期間でしたので、その詳細な説明はは書かれませんでした。 それは intchar の2つの型と、 それの配列、ポインタをサポートしており、 次のような記述に代表されるスタイルで宣言されました。

int i, j;
char c, d;
int iarray[10];
int ipointer[];
char carray[10];
char cpointer[];
The semantics of arrays remained exactly as in B and BCPL: the declarations of iarray and carray create cells dynamically initialized with a value pointing to the first of a sequence of 10 integers and characters respectively. The declarations for ipointer and cpointer omit the size, to assert that no storage should be allocated automatically. Within procedures, the language's interpretation of the pointers was identical to that of the array variables: a pointer declaration created a cell differing from an array declaration only in that the programmer was expected to assign a referent, instead of letting the compiler allocate the space and initialize the cell.
配列のセマンティックについては B と BCPL と同じ考え方が残りました: iarraycarray の宣言は各々が integer や character である 10 個の配列の先頭を指す値で動的に初期化されたセルを作成します。 記憶領域を自動的に確保しないことを示すため、 ipointercpointer の宣言ではサイズを省略します。 プロシージャの内での言語のポインターの解釈は配列変数のそれと同一でした: ポインターの宣言は、 コンパイラーがスペースを割り付け、セルを初期化する代わりに、 プログラマが対象を割り当てると期待された場合にのみ、 配列宣言と異なるセルを作りました。

Values stored in the cells bound to array and pointer names were the machine addresses, measured in bytes, of the corresponding storage area. Therefore, indirection through a pointer implied no run-time overhead to scale the pointer from word to byte offset. On the other hand, the machine code for array subscripting and pointer arithmetic now depended on the type of the array or the pointer: to compute iarray[i] or ipointer+i implied scaling the addend i by the size of the object referred to.
配列とポインタの名前に関連付けられているセルに格納された値は 記憶領域に対応するバイト単位で表されたマシンアドレスです。 したがって、 ポインタによる間接参照はワードからバイトオフセットへの変換に伴う 実行時のオーバヘッドがないことを暗示していました。 他方では、 配列の添字やポインタの演算のためのマシンコードは 配列やポインタの型に依存することになります: iarray[i]ipointer+i の計算は さん処しているオブジェクトのサイズによる i の加算を暗示していました。

These semantics represented an easy transition from B, and I experimented with them for some months. Problems became evident when I tried to extend the type notation, especially to add structured (record) types. Structures, it seemed, should map in an intuitive way onto memory in the machine, but in a structure containing an array, there was no good place to stash the pointer containing the base of the array, nor any convenient way to arrange that it be initialized. For example, the directory entries of early Unix systems might be described in C as
これらのセマンティックスは B からの容易に移行できることを意味し、 私は数か月の間それらで実験しました。 特に構造化された (レコード) タイプを加えるために、 タイプの記法を拡張しようとした時、 問題は明らかになりました。 構造体はマシンのメモリの上では直感的な方法でマップされるべきだと思えました。 しかし配列を含んでいる構造体では、 配列の基底を含んでいるポインターをしまっておくよい場所も、 それが初期化するための便利な方法もありませんでした。 例えば、初期の Unix システムのディレクトリー・エントリーは C で次のように記述されるでしょう。

struct {
	int	inumber;
	char	name[14];
};
I wanted the structure not merely to characterize an abstract object but also to describe a collection of bits that might be read from a directory. Where could the compiler hide the pointer to name that the semantics demanded? Even if structures were thought of more abstractly, and the space for pointers could be hidden somehow, how could I handle the technical problem of properly initializing these pointers when allocating a complicated object, perhaps one that specified structures containing arrays containing structures to arbitrary depth?
私は構造体が抽象的なオブジェクトを特徴づけることだけでなく、 ディレクトリーから読まれるであろうビットのコレクションについて 記述することも望みました。 コンパイラーは、セマンティックスに依存するnameを 指し示すポインタをどこに隠すことができるでしょうか? 構造体がより抽象的に考えられ、 ポインターのためのスペースを なんとかして隠せるとしても、 任意の深さの構造体を含む配列を含んでいる構造体を指定されるような 複雑なオブジェクトを割り付けた時に これらのポインタを正しく初期化する技術的な問題を どのように扱うことができるでしょうか?

The solution constituted the crucial jump in the evolutionary chain between typeless BCPL and typed C. It eliminated the materialization of the pointer in storage, and instead caused the creation of the pointer when the array name is mentioned in an expression. The rule, which survives in today's C, is that values of array type are converted, when they appear in expressions, into pointers to the first of the objects making up the array.
その解決は、 型がないBCPLとタイプされたCの間の進化の鎖の中の重大な跳躍を構成しました。 それは、 記憶装置中のポインターの実現を除去し、 配列名が表現で言及されるとき、 その代り、 ポインターの生成を引き起こしました。 規則(それは今日のCの中で残存する)は、 配列を構築するオブジェクトの1番めへのポインターへ表現に現われる場合、 配列タイプの値が変換されるということです。

This invention enabled most existing B code to continue to work, despite the underlying shift in the language's semantics. The few programs that assigned new values to an array name to adjust its origin - possible in B and BCPL, meaningless in C - were easily repaired. More important, the new language retained a coherent and workable (if unusual) explanation of the semantics of arrays, while opening the way to a more comprehensive type structure.
ほとんどの既存のBコードは、 言語の意味論の根本的な変化にもかかわらず この発明によって働き続けることができました。 その起源を調節するために配列名に新しい値を帰した 少数のプログラム? BおよびBCPL(Cにおいて無意味)において可能?容易に修理されました。 より重要なので、 より包括的な型構造への道を開いている間、 新しい言語は配列の意味論の首尾一貫して、 使用可能である(異常な場合)説明を保持しました。

The second innovation that most clearly distinguishes C from its predecessors is this fuller type structure and especially its expression in the syntax of declarations. NB offered the basic types int and char, together with arrays of them, and pointers to them, but no further ways of composition. Generalization was required: given an object of any type, it should be possible to describe a new object that gathers several into an array, yields it from a function, or is a pointer to it.
その前任者と最も明白にCの相違を示す、 第2の革新は宣言のシンタックスの このより十分な型構造および特にその表現です。 NBは多くのそれらおよびそれらへのポインターと一緒に基本型にintと炭を 提供しました、 しかしそれ以上ない構成の方法。 一般化が要求されました:任意のタイプのオブジェクトを与えられて、 いくつかのものを集めて配列に入れるか、 機能からそれを産出するか、 それへのポインターである、 新しいオブジェクトについて記述することは可能に違いありません。

For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,
そのような落ち着いているタイプの各オブジェクトについては、 根本的なオブジェクトに言及する方法が既にありました: 配列にインデックスを付けてください、 関数を呼んでください、 ポインター上で間接オペレーターを使用してください。 類推的な推論は、 名前が典型的には現われる表現シンタックスのを映す 名前用の宣言シンタックスに結びつきました。 したがって、

int i, *pi, **ppi;
declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly,
整数、整数(整数へのポインターへのポインター)へのポインターを宣言してください。これらの宣言のシンタックスは、表現の中で使用された時i*パイおよび*ppiがすべてintタイプを産出するという観察を反映します。同様に、
int f(), *f(), (*f)();
declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer;
整数、 整数(整数を返す機能へのポインター)にポインターを返す機能を返す機能を宣言します;
int *api[10], (*pai)[10];
declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.
整数への多くのポインター および多くの整数へのポインターを宣言してください。 これらのすべての場合に、変数の宣言は、 そのタイ?vが宣言の上部に指定されたタイプである表現でのその使用法に似ています。

The scheme of type composition adopted by C owes considerable debt to Algol 68, although it did not, perhaps, emerge in a form that Algol's adherents would approve of. The central notion I captured from Algol was a type structure based on atomic types (including structures), composed into arrays, pointers (references), and functions (procedures). Algol 68's concept of unions and casts also had an influence that appeared later.
それはアルゴルの支持者が承認する形式で出現しなかった(恐らく)が、 Cによって採用されたタイプ構成のスキームは相当な負債をアルゴル68に負います。 私がアルゴルから捕らえた中央の概念は上に基づいた型構造でした、 原子配列、 ポインター(参照)および機能(手続き)に整理されたタイプ(構造を含んで)。 アルゴル68の結合とキャストの概念は、さらに後に見えた影響がありました。

After creating the type system, the associated syntax, and the compiler for the new language, I felt that it deserved a new name; NB seemed insufficiently distinctive. I decided to follow the single-letter style and called it C, leaving open the question whether the name represented a progression through the alphabet or through the letters in BCPL.
タイプのシステムと関連するシンタックス、 そして新しい言語のコンパイラーを作成した後に、 私はそれが新しい名前に変えるべきだと思いました; NBでは不十分に見えました。 私は1文字のスタイルに従うことを決め、それを C と呼びました。 これにより名前が アルファベット順によるものなのか? それとも BCPL の中の次の文字が選ばれたのか? という疑問が始まります。

Neonatal C
赤ん坊の C

Rapid changes continued after the language had been named, for example the introduction of the && and || operators. In BCPL and B, the evaluation of expressions depends on context: within if and other conditional statements that compare an expression's value with zero, these languages place a special interpretation on the and (&) and or (|) operators. In ordinary contexts, they operate bitwise, but in the B statement
例えば、 言語の後に継続された迅速な変更は指定されました&&と||のオペレーターの導入。 BCPLとBでは、表現の評価が情況に依存します: の内に、場合、そして0と表現?フ値を比較する、 他の条件付きのステートメント、 これらの言語は特別の解釈を置きます、 の上で、その、そして(&)オペレーター(あるいは、(|))。 通常の情況では、それらがビット的に、だがBステートメントで作動します。

if (e1 & e2) ...
the compiler must evaluate e1 and if it is non-zero, evaluate e2, and if it too is non-zero, elaborate the statement dependent on the if. The requirement descends recursively on & and | operators within e1 and e2. The short-circuit semantics of the Boolean operators in such `truth-value' context seemed desirable, but the overloading of the operators was difficult to explain and use. At the suggestion of Alan Snyder, I introduced the && and || operators to make the mechanism more explicit.
コンパイラーはe1を評価するに違いありません。 また、それが0でない場合は、e2を評価してください、 またそれがまた0でない場合、 ステートメントを入念に作る、 依存する、 の上で、 その場合。 要求は再帰的に上に下ります。 &そして|e1の内のオペレーターまたe2.。 その、そのような「真理値」情況中のブール・オペレーターの意味論を短絡させる、 望ましく見えた、しかし、オペレーターを過負荷をかけることは、 説明するおよび使用することが困難でした。 アラン・スナイダーの提案では、私が導入しました、 その&&そして||オペレーターメカニズムをより明示的にすること。

Their tardy introduction explains an infelicity of C's precedence rules. In B one writes
それらの遅いイントロダクションは、 Cの先行規則の不適切について説明します。 Bでは、人が書きます。

if (a==b & c) ...
to check whether a equals b and c is non-zero; in such a conditional expression it is better that & have lower precedence than ==. In converting from B to C, one wants to replace & by && in such a statement; to make the conversion less painful, we decided to keep the precedence of the & operator the same relative to ==, and merely split the precedence of && slightly from &. Today, it seems that it would have been preferable to move the relative precedences of & and ==, and thereby simplify a common C idiom: to test a masked value against another value, one must write
チェックするために、 かどうか、同等のものb、また0でない;そのような条件付きの表現では、 それがよりよい、それ&BからCに切り替えることの中の==より低い先行を行っている、 一人は交換したい&そのようなステートメントでの&&によって; 転換をそれほど痛くなくするために、 私たちは、&オペレーターの先行を==への同じ関係詞にしておき単に、 今日わずかに&からの&&の先行を分割することを決定しました、 &と==の相対的な先行を移動させて、そのために、 共通のCイディオムを単純化することが望ましかっただろうように見えます: 隠れた値のテスト別の値に対して、 人は書くに違いありません。
if ((a&mask) == b) ...
where the inner parentheses are required but easily forgotten.
ここで内部の括弧は要求されるが容易に忘れられます。

Many other changes occurred around 1972-3, but the most important was the introduction of the preprocessor, partly at the urging of Alan Snyder [Snyder 74], but also in recognition of the utility of the the file-inclusion mechanisms available in BCPL and PL/I. Its original version was exceedingly simple, and provided only included files and simple string replacements: #include and #define of parameterless macros. Soon thereafter, it was extended, mostly by Mike Lesk and then by John Reiser, to incorporate macros with arguments and conditional compilation. The preprocessor was originally considered an optional adjunct to the language itself. Indeed, for some years, it was not even invoked unless the source program contained a special signal at its beginning. This attitude persisted, and explains both the incomplete integration of the syntax of the preprocessor with the rest of the language and the imprecision of its description in early reference manuals.
他の多くの変更が 1972-3 の時期に発生しましたが、 最も重要なものは、 Alan Snyder が要請していたもの [Snyder 74] の一つであり、 また BCPL および PL/I において利用可能な ファイル引用のメカニズムためのユーティリィティとして認識されていた、 プリプロセッサーの導入でした。 オリジナルバージョンは非常に単純なもので、 ファイルのインクルードと単純な文字列の置き換え: #include およびパラメーターがないマクロの #define だけが提供されました。 その後すぐに、 ほとんどは Mike Lesk によって、 そして John Reiser によって、 引数および条件付きのコンパイルをマクロを組み入れるために拡張されました。 プリプロセッサーは元々言語自体への任意の付属物だと考えられました。 実際、数年の間は、 ソース・プログラムの先頭に特別のシグナルを含んでいなければ、 起動さえされませんでした。 この考え方は固執され、 初期のリファレンスマニュアルの中では、 言語の残りとともに プリプロセッサーのシンタックスの不完全な統合と その記述の不正確さの 両方について説明されました。

Portability
ポータビリティ

By early 1973, the essentials of modern C were complete. The language and compiler were strong enough to permit us to rewrite the Unix kernel for the PDP-11 in C during the summer of that year. (Thompson had made a brief attempt to produce a system coded in an early version of C, before structures, in 1972, but gave up the effort.) Also during this period, the compiler was retargeted to other nearby machines, particularly the Honeywell 635 and IBM 360/370; because the language could not live in isolation, the prototypes for the modern libraries were developed. In particular, Lesk wrote a `portable I/O package' [Lesk 72] that was later reworked to become the C `standard I/O' routines. In 1978, Brian Kernighan and I published The C Programming Language [Kernighan 78]. Although it did not describe some additions that soon became common, this book served as the language reference until a formal standard was adopted more than ten years later. Although we worked closely together on this book, there was a clear division of labor: Kernighan wrote almost all the expository material, while I was responsible for the appendix containing the reference manual and the chapter on interfacing with the Unix system.
1973 年の初頭には、 現在の C の中心的な要素はできあがっていました。 言語およびコンパイラーはその年の夏に 私たちが C で PDP-11 の Unix カーネルを 書き直すことをできるぐらい十分に強力でした。 (1972 年に Thompson は構造体のない C の初期バージョンを使って システムのコーディングを試みましたが、失敗しました) またこの期間に、 他の身近なマシン、特に Honeywell 635 と IBM 360/370 がコンパイラーの次のターゲットとされました; 言語が単独で存在できなかったので、 現在のライブラリのプロトタイプが開発されました。 特に Lesk は、 のちに書き直され C 標準 I/O ルーチンとなった、 `portable I/O package' [Lesk 72] を書きました。 1978 年には、 Brian Kernighan と私は The C Programming Language [Kernighan 78] を出版しました。 それがすぐに一般的になったことについて 幾つかの捕捉を記述しませんでしたが、 10年以上後の公式な標準が採用されるまで、 この本は言語のリファレンスとして役立ちました。 私たちはこの本で緊密な関係で執筆を行ないましたが、 その作業には明瞭な分担がありました: 私はリファレンスマニュアルを含む付録と Unix システムでのインターフェースに関する章について 責任を負いましたが、 解説的な資料はほとんどすべて Kernighan が書きました。

During 1973-1980, the language grew a bit: the type structure gained unsigned, long, union, and enumeration types, and structures became nearly first-class objects (lacking only a notation for literals). Equally important developments appeared in its environment and the accompanying technology. Writing the Unix kernel in C had given us enough confidence in the language's usefulness and efficiency that we began to recode the system's utilities and tools as well, and then to move the most interesting among them to the other platforms. As described in [Johnson 78a], we discovered that the hardest problems in propagating Unix tools lay not in the interaction of the C language with new hardware, but in adapting to the existing software of other operating systems. Thus Steve Johnson began to work on pcc, a C compiler intended to be easy to retarget to new machines [Johnson 78b], while he, Thompson, and I began to move the Unix system itself to the Interdata 8/32 computer.
1973-1980 の間に言語は少し成長しました: 型構造には unsigned, long, union, enumeration 型が加えられました。 また構造体はほぼ first-class object になりました。 (リテラルの記法だけが欠けている) 環境とそれに伴う技術に同じように重要な開発成果が現われました。 C による Unix カーネルの記述は、 言語の有用性と効率に対する十分な確信をを私たちに与えました。 私たちがそれと同じようにシステムのユーティリィティやツールを コーディングし直し、そしてそれらの中で最も面白いものを 他のプラットフォームに移動させることを始めたからです。 [Johnson 78a] に記述されるように、 私たちは Unix ツールを広める上で最も困難な問題は 新しいハードウェアでのC言語のやりとりではなく、 他のオペレーティング・システムの既存のソフトウェアに適合させる際に 起こることを発見しました。 そこで Steve Johnson は、 彼と Thompson、および私が Interdata 8/32 コンピュータに Unix 自体を移植している間に、 新しいマシンへの対応を容易することを狙った C コンパイラである、 pcc [Johnson 78b] の作業を始めました。

The language changes during this period, especially around 1977, were largely focused on considerations of portability and type safety, in an effort to cope with the problems we foresaw and observed in moving a considerable body of code to the new Interdata platform. C at that time still manifested strong signs of its typeless origins. Pointers, for example, were barely distinguished from integral memory indices in early language manuals or extant code; the similarity of the arithmetic properties of character pointers and unsigned integers made it hard to resist the temptation to identify them. The unsigned types were added to make unsigned arithmetic available without confusing it with pointer manipulation. Similarly, the early language condoned assignments between integers and pointers, but this practice began to be discouraged; a notation for type conversions (called `casts' from the example of Algol 68) was invented to specify type conversions more explicitly. Beguiled by the example of PL/I, early C did not tie structure pointers firmly to the structures they pointed to, and permitted programmers to write pointer->member almost without regard to the type of pointer; such an expression was taken uncritically as a reference to a region of memory designated by the pointer, while the member name specified only an offset and a type.
この期間、特に 1977 年ごろの言語の変更は、 ほとんどがポータビリティと型の安全性への考慮に焦点が当てられていました。 それは新しい Interdata プラットホームへコードの相当な集まりを移動させる際に、 我々が予測し観測した問題に対処しようと努力した結果です。 その時にはまだ C はその型がなかったころの兆候を強く示していました。 例えば、 ポインターは初期の言語マニュアルや現存するコードに見出せる 完全な記憶によってなんとか識別されました; 文字ポインターと符号なしの整数の演算上の特性の類似性は、 それらを識別したい誘惑に抵抗することを困難にしました。 ポインター操作と混同することなく、 符号なしの演算を利用可能にするために、 unsigned という型が追加されました。 同様に、初期の言語は整数とポインターの間の代入を黙認しましたが、 この試みは希望が失われ始めました; (Algol 68の事例からキャストと呼ばれる) 型変換の記法は型変換をより明示的に指定するために発明されました。 PL/I の事例に惑わされて、 初期の C はそれが指した構造体へのポインターを堅く結び付けず、 まったく pointer の型と関連づけることなく、 pointer->member と書くことをプログラマに許しました。 そのような表現は メンバー名は型とオフセットのみを指定し、 ポインターによって指定されたメモリ領域への参照として、 無批判に使われました。

Although the first edition of K&R described most of the rules that brought C's type structure to its present form, many programs written in the older, more relaxed style persisted, and so did compilers that tolerated it. To encourage people to pay more attention to the official language rules, to detect legal but suspicious constructions, and to help find interface mismatches undetectable with simple mechanisms for separate compilation, Steve Johnson adapted his pcc compiler to produce lint [Johnson 79b], which scanned a set of files and remarked on dubious constructions.
K&R の第1版は C の型構造の現在の形式によるほとんどのルールを記述したのですが、 多くのプログラムはそれ以前に書かれたもので、 より緩やかなスタイルを主張したので、 それを許容するコンパイラを作りました。 人々に 公式な言語規則により多くの注意を払い、 (文法上は) 正しいが奇妙な構文を検知することを奨励し、 分割コンパイルのための単純なメカニズムでは検出できない インターフェースの不整合を見つける手助けをするため、 Steve Johnson は彼の pcc コンパイラに、 複数のファイルを走査し、曖昧な構文について注意をする lint を実現するように改造しました。[Johnson 79b]

Growth in Usage
利用の拡大

The success of our portability experiment on the Interdata 8/32 soon led to another by Tom London and John Reiser on the DEC VAX 11/780. This machine became much more popular than the Interdata, and Unix and the C language began to spread rapidly, both within AT&T and outside. Although by the middle 1970s Unix was in use by a variety of projects within the Bell System as well as a small group of research-oriented industrial, academic, and government organizations outside our company, its real growth began only after portability had been achieved. Of particular note were the System III and System V versions of the system from the emerging Computer Systems division of AT&T, based on work by the company's development and research groups, and the BSD series of releases by the University of California at Berkeley that derived from research organizations in Bell Laboratories.
#### Interdata 8/32の上の私たちのポータビリティ実験の成功は、 すぐにDEC VAX 11/780の上でトム・ロンドンおよびジョンReiserによって 別のものに結びつきました。 この機械はInterdataよりはるかにポピュラーになりました。 また、UnixおよびC言語は両方のAT&の内に、 急速に広がり始めました;Tと外部。中央の1970年代までに、 Unixは私たちの会社の外の研究指向の産業で、 学術的で、政府組織の小集団と同様にベルシステム内の様々なプロジェクトに 使用されていましたが、ポータビリティが達成された後だけ、 その実質成長は始まりました。 特別のノートに、AT&Tの新興のComputerシステムズの部門からの システムのシステムIIIおよびSystem Vバージョンが、 ベル研究所の調査機関に由来したカリフォルニア大学バークレー校によって、 会社の開発および研究グループによる仕事 およびリリースのBSDシリーズに基づいてありました。

During the 1980s the use of the C language spread widely, and compilers became available on nearly every machine architecture and operating system; in particular it became popular as a programming tool for personal computers, both for manufacturers of commercial software for these machines, and for end-users interesting in programming. At the start of the decade, nearly every compiler was based on Johnson's pcc; by 1985 there were many independently-produced compiler products.
1980年代に、 C言語の使用は広く広がりました。 また、コンパイラーは、 ほぼすべてのマシン・アーキテクチャーおよび オペレーティング・システムで利用可能になりました; それは特に、パソコン用の、 これらのマシン用の商用ソフトウェアの両方のメーカー用の、 およびプログラミングにおいて面白いエンドユーザのための プログラミング・ツールのようにポピュラーになりました。 その十年間の最初では、ほぼすべてのコンパイラーが、 1985年までにジョンソンのpccにそこに基づきました、 多くの独立して生成されたコンパイラー製品でした。

Standardization
標準化

By 1982 it was clear that C needed formal standardization. The best approximation to a standard, the first edition of K&R, no longer described the language in actual use; in particular, it mentioned neither the void or enum types. While it foreshadowed the newer approach to structures, only after it was published did the language support assigning them, passing them to and from functions, and associating the names of members firmly with the structure or union containing them. Although compilers distributed by AT&T incorporated these changes, and most of the purveyors of compilers not based on pcc quickly picked up them up, there remained no complete, authoritative description of the language.
1982年までに、 Cが形式上の標準化を必要としたことは明らかでした。 標準、K&の第一版への最良の近似;R、 もはや実際の使用に言語について記述していない; それは特にどちらの無効のタイプあるいはenumタイプにも言及しませんでした。 公表された後だけ、それが構造へのより新しいアプローチを予示した一方、 それらを割り当てる言語支援を行った、 機能間でそれらを渡しそれらを含んでいる構造か 結合にメンバーの名前を堅く関連させること。 であるが、AT&によって分配されたコンパイラー;T はこれらの変更、およびpccに速く基づかないコンパイラーの ほとんどの御用達を組込みました、 それらを拾い上げた、 言語の完全な権威のある記述は残りませんでした。

The first edition of K&R was also insufficiently precise on many details of the language, and it became increasingly impractical to regard pcc as a `reference compiler;' it did not perfectly embody even the language described by K&R, let alone subsequent extensions. Finally, the incipient use of C in projects subject to commercial and government contract meant that the imprimatur of an official standard was important. Thus (at the urging of M. D. McIlroy), ANSI established the X3J11 committee under the direction of CBEMA in the summer of 1983, with the goal of producing a C standard. X3J11 produced its report [ANSI 89] at the end of 1989, and subsequently this standard was accepted by ISO as ISO/IEC 9899-1990.
K&の第一版;さらに、Rは、言語の多くの詳細上で不適当に正確でした。 また、pccを「参照コンパイラー」と見なすことは ますます非実用的になりました;それは、 K&によって記述された言語さえ完全に具体化しませんでした; 後の拡張はいうまでもなくR。 最後に、コマーシャルおよび政府契約に従うプロジェクトでのCの発端の使用は、 公式規格の刊行許可が重要であることを意味しました。 したがって(M.D.McIlroyを促すことで)、 ANSIはC標準を生産するゴールと共に、 1983の夏にCBEMAの指導のもとにX3J11委員会を設立しました。 X3J11は1989年末にその報告書[ANSI 89]を生産しました。 また、続いて、この標準はISO/IEC 9899-1990としてISOによって認められました。

From the beginning, the X3J11 committee took a cautious, conservative view of language extensions. Much to my satisfaction, they took seriously their goal: `to develop a clear, consistent, and unambiguous Standard for the C programming language which codifies the common, existing definition of C and which promotes the portability of user programs across C language environments.' [ANSI 89] The committee realized that mere promulgation of a standard does not make the world change.
始めから、X3J11委員会は言語拡張を用心深く保守的に見ました。 非常に、私の充足に、それらはゴールを真剣に受けとめました: 「Cの共通で既存の定義を成文化し、 それはC言語環境を横切ってユーザ・プログラムのポータビリティを促進する Cプログラミング言語用の明瞭で一貫して、 明白な?Xタンダードを開発するために。」[ANSI 89]委員会は、 標準の単なる発布が世界を変わらせないことを悟りました。

X3J11 introduced only one genuinely important change to the language itself: it incorporated the types of formal arguments in the type signature of a function, using syntax borrowed from C++ [Stroustrup 86]. In the old style, external functions were declared like this:
X3J11は言語自体に単に1つの真に重要な変更を導入しました: それは、C++[Stroustrup 86]から借りられたシンタックスを使用して、 機能のタイプ署名に形式上の議論のタイプを組み入れました。 オールドスタイルでは、外部機能がこのように宣言されました:

double sin();
which says only that sin is a function returning a double (that is, double-precision floating-point) value. In the new style, this better rendered
どれがその罪だけが2倍の (すなわち倍精度浮動小数点) 値を返す機能であると言うか。 新しいスタイルで、これはよりよく与えました。
double sin(double);
to make the argument type explicit and thus encourage better type checking and appropriate conversion. Even this addition, though it produced a noticeably better language, caused difficulties. The committee justifiably felt that simply outlawing `old-style' function definitions and declarations was not feasible, yet also agreed that the new forms were better. The inevitable compromise was as good as it could have been, though the language definition is complicated by permitting both forms, and writers of portable software must contend with compilers not yet brought up to standard.
議論タイプを明示的にし、 したがってよりよいタイプチェックおよび適切な転換を促進することために。 この追加さえ、 それは顕著によりよい言語を生成しましたが、 障害を引き起こしました。 委員会は、単に、 「オールドスタイルの」関数定義および宣言の禁止がまだ実現可能ではないと 正当に思いました、さらに新しい形式がよりよいことに合意しました。 避けられないは言語定義は両方の形式を許すことにより複雑になりますが、 それがあるかもしれないし、 ポータブルソフトウェアの作家が標準までまだもたらされない コンパイラーと争わなければならないのと同じくらいよかった。

X3J11 also introduced a host of smaller additions and adjustments, for example, the type qualifiers const and volatile, and slightly different type promotion rules. Nevertheless, the standardization process did not change the character of the language. In particular, the C standard did not attempt to specify formally the language semantics, and so there can be dispute over fine points; nevertheless, it successfully accounted for changes in usage since the original description, and is sufficiently precise to base implementations on it.
X3J11も導入しました。 多数のより小さな付加物および調節 (例えばタイプ修飾語const、揮発性で、わずかに異なるタイプ促進規則)。 しかしながら、標準化プロセスは、言語の特徴を変更しませんでした。 C標準は、言語意味論を形式的に指定することを特に試みませんでした。 したがって、細かいポイント以上論争がありえます;しかしながら、 それは、成功裡にオリジナルの記述以来使用法の変化を説明し、 それにインプリメンテーションを基づかせるのに十分に正確です。

Thus the core C language escaped nearly unscathed from the standardization process, and the Standard emerged more as a better, careful codification than a new invention. More important changes took place in the language's surroundings: the preprocessor and the library. The preprocessor performs macro substitution, using conventions distinct from the rest of the language. Its interaction with the compiler had never been well-described, and X3J11 attempted to remedy the situation. The result is noticeably better than the explanation in the first edition of K&R; besides being more comprehensive, it provides operations, like token concatenation, previously available only by accidents of implementation.
ほとんど回避された標準化プロセスから無傷の中核C言語、 およびスタンダードは新しい発明よりよい注意深い規則の成文化として もっと出現しました。より重要な変更は言語の環境で起こりました: プリプロセッサーおよび図書館。 プリプロセッサーは言語の残りとは異なる協定を使用して、 マクロの代用を実行します。 そのコンパイラーを備えた相互作用はよく記述されていませんでした。 また、X3J11は、状況を改善することを試みました。 結果は、より包括的なK&Rbesidesの第一版中の説明より顕著によい、 それは印連結(以前にインプリメンテーションの事故によってのみ利用可能) のように、オペレーションを提供します。

X3J11 correctly believed that a full and careful description of a standard C library was as important as its work on the language itself. The C language itself does not provide for input-output or any other interaction with the outside world, and thus depends on a set of standard procedures. At the time of publication of K&R, C was thought of mainly as the system programming language of Unix; although we provided examples of library routines intended to be readily transportable to other operating systems, underlying support from Unix was implicitly understood. Thus, the X3J11 committee spent much of its time designing and documenting a set of library routines required to be available in all conforming implementations.
X3J11は、 標準のC図書館の詳細で注意深い記述が言語自体の その研究と同じくらい重要であると正確に信じました。 C言語はそれ自体提供しません、のために、入出力、 あるいは外部の世界を備えた他の相互作用、 またしたがって1セットの標準の手続きに依存します。 K&Rの出版の時に、Cは、主としてUnixのシステム・プログラミング言語と 見なされました;私たちは容易に他のオペレーティング・システムに 運送可能であると意図したライブラリー・ルーチンの例を提供しましたが、 Unixからの根本的なサポートは暗黙に理解されました。 したがって、X3J11委員会は、その時間デザイニングの多く およびセットをドキュメント化することを費やしました。 すべての一致するインプリメンテーションにおいて 利用可能なのに必要なライブラリー・ルーチンの。

By the rules of the standards process, the current activity of the X3J11 committee is confined to issuing interpretations on the existing standard. However, an informal group originally convened by Rex Jaeschke as NCEG (Numerical C Extensions Group) has been officially accepted as subgroup X3J11.1, and they continue to consider extensions to C. As the name implies, many of these possible extensions are intended to make the language more suitable for numerical use: for example, multi-dimensional arrays whose bounds are dynamically determined, incorporation of facilities for dealing with IEEE arithmetic, and making the language more effective on machines with vector or other advanced architectural features. Not all the possible extensions are specifically numerical; they include a notation for structure literals.
標準プロセスの規則によって、 X3J11委員会の現在の活動は既存の標準上の解釈を出すことに制限されます。 しかしながら、NCEG(数のC拡張グループ)としてレックスJaeschkeによって もとは召集された非公式のグループは、 サブグループX3J11.1として公式に認められました。 また、それらは、Cに対する拡張を考慮し続けます。 名前が意味するとともに、これらの可能な拡張の多くは言語を数の使用に、 よりふさわしくするように意図されます: 例えば、その境界がダイナミックに決定される多次元の配列、 IEEEの算術に対処し、 ベクトルで言語を機械上でより有効にするための施設の編入あるいは他のものは、 建築上の特徴を進めました。 すべての可能な拡張は特に数だとは限りません; それらは、構造リテラル用の記法を含んでいます。

Successors
後継者

C and even B have several direct descendants, though they do not rival Pascal in generating progeny. One side branch developed early. When Steve Johnson visited the University of Waterloo on sabbatical in 1972, he brought B with him. It became popular on the Honeywell machines there, and later spawned Eh and Zed (the Canadian answers to `what follows B?'). When Johnson returned to Bell Labs in 1973, he was disconcerted to find that the language whose seeds he brought to Canada had evolved back home; even his own yacc program had been rewritten in C, by Alan Snyder.
それらは子孫の生成においてパスカルに匹敵しませんが、 CおよびBさえは数人の直接の子孫を持っています。 1本の側枝は初期に発展しました。 スティーヴ・ジョンソンが1972年に一年間の有給休暇の上の ワーテルローの大学を訪れた時彼はBを持って来ました。 それはそこでハネウェルの機械上でポピュラーになり、 えっ、およびZ(カナダの答え、に「Bに続くもの?')をその後大量に産みました。 ジョンソンが1973年にベル研究所に戻った時、 彼は彼がカナダへ持って来たその種子が持っていた言語が 後ろに家へ発展したことを知るために心が動揺しました; 自分のyaccプログラムさえアラン・スナイダーによって Cの中で書き直されました。

More recent descendants of C proper include Concurrent C [Gehani 89], Objective C [Cox 86], C* [Thinking 90], and especially C++ [Stroustrup 86]. The language is also widely used as an intermediate representation (essentially, as a portable assembly language) for a wide variety of compilers, both for direct descendents like C++, and independent languages like Modula 3 [Nelson 91] and Eiffel [Meyer 88].
適切なCのより最近の子孫は同時的なC[Gehani 89]、 目的C[コックス86]、C*[思考90]および特にC++[Stroustrup 86]を含みます。 言語も、C++のような直接の子孫およびModula 3[ネルソン91]のような 独立した言語の両方、ならびにエッフェルのために、 種々様々のコンパイラーのための中間の表現 (本質的にポータブルのアセンブリ言語としての) として広く使用されます。[マイヤー88]。

Critique
批評

Two ideas are most characteristic of C among languages of its class: the relationship between arrays and pointers, and the way in which declaration syntax mimics expression syntax. They are also among its most frequently criticized features, and often serve as stumbling blocks to the beginner. In both cases, historical accidents or mistakes have exacerbated their difficulty. The most important of these has been the tolerance of C compilers to errors in type. As should be clear from the history above, C evolved from typeless languages. It did not suddenly appear to its earliest users and developers as an entirely new language with its own rules; instead we continually had to adapt existing programs as the language developed, and make allowance for an existing body of code. (Later, the ANSI X3J11 committee standardizing C would face the same problem.)
2つの考えがそのクラスの言語中のCのほとんどの特性です: 配列とポインターの関係、 および宣言シンタックスが表現シンタックスを模倣する方法。 それらはさらにその最も頻繁に批評された特徴中にあり、 初心者に障害としてしばしば役立ちます。 両方の場合では、 歴史上の事故あるいは誤りがそれらの困難を悪化させました。 最も重要なもの(これらに)はタイプにおけるエラーへのCコンパイラーに対する 耐性でした。上記の歴史から明らかであるべきとして、 Cは型がない言語から発展しました。それは、急に、 それ自身の規則を備えた完全に新しい言語として その最も初期のユーザおよび開発者に現われませんでした; 代わりに、私たちは、連続的に開発されていた言語として 既存のプログラムを適応させし、コードの既存の集まりのための 費用を行なわなければなりませんでした。 (その後、Cを標準化するANSI X3J11委員会は同じ問題に直面するでしょう。)

Compilers in 1977, and even well after, did not complain about usages such as assigning between integers and pointers or using objects of the wrong type to refer to structure members. Although the language definition presented in the first edition of K&R was reasonably (though not completely) coherent in its treatment of type rules, that book admitted that existing compilers didn't enforce them. Moreover, some rules designed to ease early transitions contributed to later confusion. For example, the empty square brackets in the function declaration
1977年のコンパイラー、 そ?オて後によくさえ、整数とポインターの間に割り当てるか、 メンバーを組み立てるために参照するために間違っているタイプの オブジェクトを使用するような使用法について苦情を言いませんでした。 言語定義はK&の第一版の中で示しましたが;Rは、 タイプ規則のその処理において合理的に(が、完全でなく)首尾一貫しました、 本は、既存のコンパイラーがそれらを強化しないと認めました。 さらに、初期の推移を緩和することを目指したいくつかの規則は 後の混乱に寄与しました。例えば関数宣言での空の角括弧

int f(a) int a[]; { ... }
are a living fossil, a remnant of NB's way of declaring a pointer; a is, in this special case only, interpreted in C as a pointer. The notation survived in part for the sake of compatibility, in part under the rationalization that it would allow programmers to communicate to their readers an intent to pass f a pointer generated from an array, rather than a reference to a single integer. Unfortunately, it serves as much to confuse the learner as to alert the reader.
生きた化石(ポインターを宣言するNBの方法の残り)です; 1つの、ポインターとしてCの中で解釈されたこの特別の場合のみでのis。 一部分それが許可する合理化の下で一部分互換性のために残存された記法、 それらのリーダに通過する意図を伝えるプログラマ 単一の整数への言及ではなく、 配列からポインターが生成したf。 不運にも、警戒に関して学習者を混乱させるために、 それは多くとしてリーダに役立ちます。

In K&R C, supplying arguments of the proper type to a function call was the responsibility of the programmer, and the extant compilers did not check for type agreement. The failure of the original language to include argument types in the type signature of a function was a significant weakness, indeed the one that required the X3J11 committee's boldest and most painful innovation to repair. The early design is explained (if not justified) by my avoidance of technological problems, especially cross-checking between separately-compiled source files, and my incomplete assimilation of the implications of moving between an untyped to a typed language. The lint program, mentioned above, tried to alleviate the problem: among its other functions, lint checks the consistency and coherency of a whole program by scanning a set of source files, comparing the types of function arguments used in calls with those in their definitions.
K&R Cでは、関数呼び出しに適切なタイプの議論を供給することが プログラマの責任でした。また、残存するコンパイラーは タイプ協定をチェックしませんでした。 オリジナルの言語の議論を含めることの失敗は、 機能のタイプ署名をタイプインします、確かに重要な弱さだった、 修理するX3J11委員会の最も大胆で最も痛い革新を要求したもの。 初期の設計は、技術的な問題、特に別々にコンパイルされた ソース・ファイル間のクロスチェッキング、 およびタイプされた言語にuntypedの間に移る含意の 私の不完全な同化の私の回避によって説明されます (正当化されなかったにしても)。 その上に言及されたリント・プログラムは、 その問題を緩和しようとしました: その他の関数の中で、リントは、 それらの定義中のものを備えた呼び出しの中で 使用される関数議論のタイプを比較して、 1セットのソース・ファイルの走査により 全体のプログラムの一貫性および統一をチェックします。

An accident of syntax contributed to the perceived complexity of the language. The indirection operator, spelled * in C, is syntactically a unary prefix operator, just as in BCPL and B. This works well in simple expressions, but in more complex cases, parentheses are required to direct the parsing. For example, to distinguish indirection through the value returned by a function from calling a function designated by a pointer, one writes *fp() and (*pf)() respectively. The style used in expressions carries through to declarations, so the names might be declared
シンタックスの事故は、 言語の知覚された複雑さに寄与しました。 間接オペレーター、 綴られました* ちょうどBCPLとBでのように、 Cでは、構文上単項の接頭辞オペレーターです。 これは単純な表現でうまくいきます。 しかし、より複雑な場合では、 括弧が解析を指図するために要求されます。 例えば、関数をポインターによって指定されたと 呼ぶから関数によって返された値によって間接を識別するために、 1つは書きます。* fp()および()(*pf)それぞれ。 表現の中で使用されるスタイルは、宣言に通り抜けて達します。 したがって、名前は宣言されるかもしれません。

int *fp();
int (*pf)();
In more ornate but still realistic cases, things become worse:
の中で、さらに華麗であるが、まだ現実的な場合、事態はより悪くなります:
int *(*pfp)();
is a pointer to a function returning a pointer to an integer. There are two effects occurring. Most important, C has a relatively rich set of ways of describing types (compared, say, with Pascal). Declarations in languages as expressive as C - Algol 68, for example - describe objects equally hard to understand, simply because the objects themselves are complex. A second effect owes to details of the syntax. Declarations in C must be read in an `inside-out' style that many find difficult to grasp [Anderson 80]. Sethi [Sethi 81] observed that many of the nested declarations and expressions would become simpler if the indirection operator had been taken as a postfix operator instead of prefix, but by then it was too late to change.
整数にポインターを返す機能へのポインターです。 2つの結果が生じています。最も重要、 Cは、タイプ(パスカルと、例えば比較された) について記述する方法の比較的豊富なセットを持っています。 C&Algol 68ほど表現する言語の宣言、 example&describeのために、 単にオブジェクトがそれら自身複雑なというだけの理由で、 理解するために等しく激しく反対します。 別の結果はシンタックスの詳細に借りがあります。 Cの中の宣言は読まれるに違いありません、1つの、 の内部でアウト、 多数が理解?キることが困難に感じるスタイル[アンダーソン80]。 Sethi[Sethi 81]は、 もし間接オペレーターが接頭辞の代わりに接尾辞オペレーターと 考えられていたならば、入れ子の宣言および表現の多くが より単純になるだろうと言ったが、その時までに、 それは遅すぎたので、変更することができませんでした。

In spite of its difficulties, I believe that the C's approach to declarations remains plausible, and am comfortable with it; it is a useful unifying principle.
その障害にもかかわらず、 私は、Cの宣言へのアプローチが妥当性のあるままであると信じて、 それに満足しています;それは有用な統一する原理です。

The other characteristic feature of C, its treatment of arrays, is more suspect on practical grounds, though it also has real virtues. Although the relationship between pointers and arrays is unusual, it can be learned. Moreover, the language shows considerable power to describe important concepts, for example, vectors whose length varies at run time, with only a few basic rules and conventions. In particular, character strings are handled by the same mechanisms as any other array, plus the convention that a null character terminates a string. It is interesting to compare C's approach with that of two nearly contemporaneous languages, Algol 68 and Pascal [Jensen 74]. Arrays in Algol 68 either have fixed bounds, or are `flexible:' considerable mechanism is required both in the language definition, and in compilers, to accommodate flexible arrays (and not all compilers fully implement them.) Original Pascal had only fixed-sized arrays and strings, and this proved confining [Kernighan 81]. Later, this was partially fixed, though the resulting language is not yet universally available.
さらに、 それは実際の美徳を持ちますが、 C(配列のその処理)の別の特有の特徴は実際的なグラウンドでより疑わしい。 ポインターと配列の関係は異常ですが、 それは学習することができます。 さらに、言語は、 ほんの少数の基礎的な規則および協定で相当な力が 重要な概念(例えばその長さがランタイムで変わるベクトル)について 記述することを示します。 文字ストリングは、特に、無効の特徴がストリングを終了するという 慣例を加えて他の配列と同じメカニズムによって扱われます。 2つのほとんど同時の言語、アルゴル68およびパスカル[ジェ?塔Zン74]の それとCのアプローチを比較することは面白い。 アルゴル68中の配列は境界を固定したか、 あるいは「柔軟である」:相当なメカニズムは 柔軟な配列 (また、すべてのコンパイラーは完全にそれらをインプリメントするとは限りません。) を提供するために言語定義中で、およびコンパイラー中で要求されます。 オリジナルのパスカルは持っていました、 分類されて、単に固定した、配列およびストリング、 およびこの証明された制限する[Kernighan 81]。 その後、生じる言語はまだ、普遍的に利用可能ではありませんが、 これは部分的に固定しました。

C treats strings as arrays of characters conventionally terminated by a marker. Aside from one special rule about initialization by string literals, the semantics of strings are fully subsumed by more general rules governing all arrays, and as a result the language is simpler to describe and to translate than one incorporating the string as a unique data type. Some costs accrue from its approach: certain string operations are more expensive than in other designs because application code or a library routine must occasionally search for the end of a string, because few built-in operations are available, and because the burden of storage management for strings falls more heavily on the user. Nevertheless, C's approach to strings works well.
Cは、マーカーによって慣例通りに終了した 多くの文字としてストリングを扱います。 ストリング・リテラルによって初期化に関する 1つの特別の規則に加えて、ストリングの意味論、 完全に配列をすべて管理する、 より一般的な規則によって、 およびその結果入れられる、 ユニークなデータ・タイプとしてストリングを組込んで、 1より言語について記述し翻訳することはより簡単です。 いくつかのコストはそのアプローチから生じます: 適用コードあるいはライブラリー・ルーチンが ストリングの端を時々探索しなければならないので、 およびほとんどの内蔵のオペレーションが利用可能でないので、 およびストリング用ストレージ管理の負担がユーザにより 極度に降りかかるので、 あるストリング・オペレーションは他の設計の中でよりも高価です。 しかしながら、Cのストリングへのアプローチはうまくいきます。

On the other hand, C's treatment of arrays in general (not just strings) has unfortunate implications both for optimization and for future extensions. The prevalence of pointers in C programs, whether those declared explicitly or arising from arrays, means that optimizers must be cautious, and must use careful dataflow techniques to achieve good results. Sophisticated compilers can understand what most pointers can possibly change, but some important usages remain difficult to analyze. For example, functions with pointer arguments derived from arrays are hard to compile into efficient code on vector machines, because it is seldom possible to determine that one argument pointer does not overlap data also referred to by another argument, or accessible externally. More fundamentally, the definition of C so specifically describes the semantics of arrays that changes or extensions treating arrays as more primitive objects, and permitting operations on them as wholes, become hard to fit into the existing language. Even extensions to permit the declaration and use of multidimensional arrays whose size is determined dynamically are not entirely straightforward [MacDonald 89] [Ritchie 90], although they would make it much easier to write numerical libraries in C. Thus, C covers the most important uses of strings and arrays arising in practice by a uniform and simple mechanism, but leaves problems for highly efficient implementations and for extensions.
他方では、 Cの一般(単なるストリングではない) に配列の処理は、最適化のための、 および将来の拡張のための不運な意味合いを持ちます。 Cプログラム中のポインターの普及、 かどうか、明示的に公言されているか、 配列から発生するもの、 オプティマイザーがそうであるに違いない手段、 用心深い、 また好結果を達成するために注意深い データ・フロー技術を使用するに違いありません。 精巧なコンパイラーは、 ほとんどのポインターがどうしても何を変更することができるか 理解することができます。 しかし、いくつかの重要な使用法は分析することが困難なままです。 例えば、それを決定することがめったに可能でないので、 ベクトル機械上の効率的なコードへ配列に由来した ポインター議論を備えた機能をコンパイルすることは難しい、 議論ポインターはデータをオーバーラップさせません、 さらに参照した、に、別の議論によって、 あるいはアクセス可能、外部的に。 多くの、基本的に、Cの定義、したがって、 特に、配列の意味論について記述する、それ、 変更あるいは拡張、より原始的なオブジェクトとしての扱う配列、 またそれらに対する可能にするオペレーション、 wholesとして、なる、困難、既存の言語に入るために それらはC.の中で数の図書館をしたがって書くことをはるかに容易にするが、 そのサイズがダイナミックに決定される多次元の配列の宣言 および使用を許す拡張さえ、完全にあけすけな[マクドナルド89] [リッチー90]ではありません、Cは最も重要なものをカバーします、 一定で単純なメカニズムによって実際上発生するストリング および配列に使用するが、 高度に効率的なインプリメンテーションおよび拡張に問題を残す。

Many smaller infelicities exist in the language and its description besides those discussed above, of course. There are also general criticisms to be lodged that transcend detailed points. Chief among these is that the language and its generally-expected environment provide little help for writing very large systems. The naming structure provides only two main levels, `external' (visible everywhere) and `internal' (within a single procedure). An intermediate level of visibility (within a single file of data and procedures) is weakly tied to the language definition. Thus, there is little direct support for modularization, and project designers are forced to create their own conventions.
多くのより小さな不適切が言語およびその記述で存在します。 もちろん、そのほかに、それらは上に議論しました。 そこで、詳細なポイントを超越する泊まるさらに一般的な批判はあります。 これらの中で主要なのは、 言語およびその一般に予期された環境が非常に大規模なシステムを 書くために支援をほとんど提供しないということです。 指定する構造はたった2メイン・レベル、 「外部」(どこでも目に見える)および「内部」(単一の手続きの内に)しか 提供しません。中間のレベル視界(データと手続きの単一のファイル内の)の、 弱く言語定義に結?ム付けられます。したがって、 モジュール化の直接の支援はほとんどありません。 また、プロジェクト・デザイナーは、自分の協定を作ることを強いられます。

Similarly, C itself provides two durations of storage: `automatic' objects that exist while control resides in or below a procedure, and `static,' existing throughout execution of a program. Off-stack, dynamically-allocated storage is provided only by a library routine and the burden of managing it is placed on the programmer: C is hostile to automatic garbage collection.
同様に、Cはそれ自身、記憶装置の2つの持続を提供します: コントロールが手続きに、あるいはaその手続き以下に存在している一方、 存在する「自動」オブジェクト、そして「静止の」、 プログラムの実行の全体にわたって既存。 オフスタックおよびダイナミックに割り付けられた記憶装置は ライブラリー・ルーチンによってのみ提供されます。 また、それを管理する負担は、プログラマに置かれます: Cは自動ガーベジ・コレクションに敵対しています。

Whence Success?
どこから成功?

C has become successful to an extent far surpassing any early expectations. What qualities contributed to its widespread use?
Cは、遠くにどんな初期の期待も越える程度まで 成功するようになりました。 どの特質がその広範囲の使用に寄与しましたか。

Doubtless the success of Unix itself was the most important factor; it made the language available to hundreds of thousands of people. Conversely, of course, Unix's use of C and its consequent portability to a wide variety of machines was important in the system's success. But the language's invasion of other environments suggests more fundamental merits.
確かに、Unix自体の成功は最多の重要な要素でした; それは言語を何十万もの人々に利用可能にしました。 反対に、もちろん、UnixのCおよび種々様々の機械への その必然のポータビリティの使用は、 システムの成功において重要でした。 しかし、言語の他の環境の侵入はより多くの基本の長所を示唆します。

Despite some aspects mysterious to the beginner and occasionally even to the adept, C remains a simple and small language, translatable with simple and small compilers. Its types and operations are well-grounded in those provided by real machines, and for people used to how computers work, learning the idioms for generating time- and space-efficient programs is not difficult. At the same time the language is sufficiently abstracted from machine details that program portability can be achieved.
初心者に、 および時々熟達するにさえ不可解ないくつかの様相にもかかわらず、 Cは単純で小さな言語(単純で小さなコンパイラーで翻訳可能)のままです。 そのタイプおよびオペレーションは、 上手に本物の機械によって提供されるものに根ざしています。 また、コンピューターがどのように作動するかに使われる人々にとって、 時間かつスペース効率的なプログラムの生成のためにイディオムを 学習することは困難ではありません。 言語が機械詳細から十分に抽象されるのと同じ時に、 そのプログラム・ポータビリティは達成することができます。

Equally important, C and its central library support always remained in touch with a real environment. It was not designed in isolation to prove a point, or to serve as an example, but as a tool to write programs that did useful things; it was always meant to interact with a larger operating system, and was regarded as a tool to build larger tools. A parsimonious, pragmatic approach influenced the things that went into C: it covers the essential needs of many programmers, but does not try to supply too much.
等しく重要、 Cおよびその中央の図書館は支援します、 常に実際の環境を備えたタッチに残りました。 それは、ポイントを証明するかあるいは例だが有用な 物事を行ったプログラムを書くツールとして 役立つためには分離して設計されませんでした; それは常により大きなオペレーティング・システムと 対話するというつもりで、 より大きなツールを建造するツールと見なされました。 しみったれて実用的なアプローチは、 Cに入った物事に影響を及ぼしました: それはカバーします。多くのプログラマの本質的な必要、 しかしあまりに供給しようとしません。

Finally, despite the changes that it has undergone since its first published description, which was admittedly informal and incomplete, the actual C language as seen by millions of users using many different compilers has remained remarkably stable and unified compared to those of similarly widespread currency, for example Pascal and Fortran. There are differing dialects of C - most noticeably, those described by the older K&R and the newer Standard C - but on the whole, C has remained freer of proprietary extensions than other languages. Perhaps the most significant extensions are the `far' and `near' pointer qualifications intended to deal with peculiarities of some Intel processors. Although C was not originally designed with portability as a prime goal, it succeeded in expressing programs, even including operating systems, on machines ranging from the smallest personal computers through the mightiest supercomputers.
最後に、 その最初の公表された記述 (それは明白に非公式で不完全だった) 以来それが経験した変更にもかかわらず、 様々なコンパイラーを使用して、 何百万ものユーザによって見られるような実際のC言語は、 著しく安定していて一体になっていたままでした、 同様に広範囲の普及(例えばパスカル、フォートラン)のものに 匹敵しました。 Cの異なる方言があります? 顕著に、それらは、より古いK&Rおよびより新しい標準のCによって記述しました? しかし、概して、Cは、他の言語より所有者の拡張の自由にする人のままでした。 恐らく、最も著しい拡張はそうです、その、遠くに「そしての近くで」 ポインター資格は、 いくつかのインテル・プロセッサーの特色に対処するつもりでした。 Cは??のゴールとしてポータビリティで元来設計されませんでしたが、 それは、最も小さなパソコンから最も強力なスーパー・コンピューターまで 及ぶマシン上で、オペレーティング・システムをさらに含めて、 表現するプログラムに成功しました。

C is quirky, flawed, and an enormous success. While accidents of history surely helped, it evidently satisfied a need for a system implementation language efficient enough to displace assembly language, yet sufficiently abstract and fluent to describe algorithms and interactions in a wide variety of environments.
Cは逃げ口上が多い、 欠陥のある、 また巨大な成功。 歴史の事故が確実に助けになった一方、 それは明白に種々様々の環境にアルゴリズムと相互作用について 記述するのにまだ、 十分に抽象的で流暢であるアセンブリ言語を置き換えるために 十分に効率的なシステム・インプリメンテーション言語の必要を満たしました。

Acknowledgments
認識

It is worth summarizing compactly the roles of the direct contributors to today's C language. Ken Thompson created the B language in 1969-70; it was derived directly from Martin Richards's BCPL. Dennis Ritchie turned B into C during 1971-73, keeping most of B's syntax while adding types and many other changes, and writing the first compiler. Ritchie, Alan Snyder, Steven C. Johnson, Michael Lesk, and Thompson contributed language ideas during 1972-1977, and Johnson's portable compiler remains widely used. During this period, the collection of library routines grew considerably, thanks to these people and many others at Bell Laboratories. In 1978, Brian Kernighan and Ritchie wrote the book that became the language definition for several years. Beginning in 1983, the ANSI X3J11 committee standardized the language. Especially notable in keeping its efforts on track were its officers Jim Brodie, Tom Plum, and P. J. Plauger, and the successive draft redactors, Larry Rosler and Dave Prosser.
それは、今日のC言語への直接の寄稿家の役割を簡潔に要約する価値があります。 ケン・トムプソンは1969-70にB言語を作成しました; それは、マーティン・リチャーズのBCPLに直接由来しました。 デニス・リッチーは、タイプおよび他の多くの変更を加えて、 第1のコンパイラーを書く間にBのシンタックスのうちのほとんどを維持して、 1971-73にBをCに変えました。 リッチー、アラン・スナイダー、スティーヴンC.ジョンソン、マイケルLeskおよび トムプソンは、1972-1977に言語考えを与えました。 また、ジョンソンのポータブルコンパイラーは使用されて、 広く残ります。この期間に、ライブラリー・ルーチンの収集は、 これらの人々およびベル研究所での他に多くのもののおかげで、 相当に成長しました。1978年には、ブライアンKernighanおよびリッチーが、 数年間言語定義になった本を書きました。 1983年に始めて、ANSI X3J11委員会は言語を標準化しました。 軌道上でその努力を維持することにおいて特に顕著、 そのオフィサー、ジムBrodie、トム・プラムおよび P.J.Plaugerだった、また連続の草案の編集者、 ラリーRoslerおよびディヴ・プロッサー。

I thank Brian Kernighan, Doug McIlroy, Dave Prosser, Peter Nelson, Rob Pike, Ken Thompson, and HOPL's referees for advice in the preparation of this paper.
私はブライアンKernighanに感謝します、ダグMcIlroy、ディヴ・プロッサー、ピーター・ネルソン、この論文の準備での助言用の槍、ケン・トムプソンおよびHOPLのレフェリーから奪います。

References



[ANSI 89]
American National Standards Institute, American National Standard for Information Systems­Programming Language C, X3.159-1989.
[Anderson 80]
B. Anderson, `Type syntax in the language C: an object lesson in syntactic innovation,' SIGPLAN Notices 15 (3), March, 1980, pp. 21-27.
[Bell 72]
J. R. Bell, `Threaded Code,' C. ACM 16 (6), pp. 370-372.
[Canaday 69]
R. H. Canaday and D. M. Ritchie, `Bell Laboratories BCPL,' AT&T Bell Laboratories internal memorandum, May, 1969.
[Corbato 62]
F. J. Corbato, M. Merwin-Dagget, R. C. Daley, `An Experimental Time-sharing System,' AFIPS Conf. Proc. SJCC, 1962, pp. 335-344.
[Cox 86]
B. J. Cox and A. J. Novobilski, Object-Oriented Programming: An Evolutionary Approach, Addison-Wesley: Reading, Mass., 1986. Second edition, 1991.
[Gehani 89]
N. H. Gehani and W. D. Roome, Concurrent C, Silicon Press: Summit, NJ, 1989.
[Jensen 74]
K. Jensen and N. Wirth, Pascal User Manual and Report, Springer-Verlag: New York, Heidelberg, Berlin. Second Edition, 1974.
[Johnson 73]
S. C. Johnson and B. W. Kernighan, `The Programming Language B,' Comp. Sci. Tech. Report #8, AT&T Bell Laboratories (January 1973).
[Johnson 78a]
S. C. Johnson and D. M. Ritchie, `Portability of C Programs and the UNIX System,' Bell Sys. Tech. J. 57 (6) (part 2), July-Aug, 1978.
[Johnson 78b]
S. C. Johnson, `A Portable Compiler: Theory and Practice,' Proc. 5th ACM POPL Symposium (January 1978).
[Johnson 79a]
S. C. Johnson, `Yet another compiler-compiler,' in Unix Programmer's Manual, Seventh Edition, Vol. 2A, M. D. McIlroy and B. W. Kernighan, eds. AT&T Bell Laboratories: Murray Hill, NJ, 1979.
[Johnson 79b]
S. C. Johnson, `Lint, a Program Checker,' in Unix Programmer's Manual, Seventh Edition, Vol. 2B, M. D. McIlroy and B. W. Kernighan, eds. AT&T Bell Laboratories: Murray Hill, NJ, 1979.
[Kernighan 78]
B. W. Kernighan and D. M. Ritchie, The C Programming Language, Prentice-Hall: Englewood Cliffs, NJ, 1978. Second edition, 1988.
[Kernighan 81]
B. W. Kernighan, `Why Pascal is not my favorite programming language,' Comp. Sci. Tech. Rep. #100, AT&T Bell Laboratories, 1981.
[Lesk 73]
M. E. Lesk, `A Portable I/O Package,' AT&T Bell Laboratories internal memorandum ca. 1973.
[MacDonald 89]
T. MacDonald, `Arrays of variable length,' J. C Lang. Trans 1 (3), Dec. 1989, pp. 215-233.
[McClure 65]
R. M. McClure, `TMG - A Syntax Directed Compiler,' Proc. 20th ACM National Conf. (1965), pp. 262-274.
[McIlroy 60]
M. D. McIlroy, `Macro Instruction Extensions of Compiler Languages,' C. ACM 3 (4), pp. 214-220.
[McIlroy 79]
M. D. McIlroy and B. W. Kernighan, eds, Unix Programmer's Manual, Seventh Edition, Vol. I, AT&T Bell Laboratories: Murray Hill, NJ, 1979.
[Meyer 88]
B. Meyer, Object-oriented Software Construction, Prentice-Hall: Englewood Cliffs, NJ, 1988.
[Nelson 91]
G. Nelson, Systems Programming with Modula-3, Prentice-Hall: Englewood Cliffs, NJ, 1991.
[Organick 75]
E. I. Organick, The Multics System: An Examination of its Structure, MIT Press: Cambridge, Mass., 1975.
[Richards 67]
M. Richards, `The BCPL Reference Manual,' MIT Project MAC Memorandum M-352, July 1967.
[Richards 79]
M. Richards and C. Whitbey-Strevens, BCPL: The Language and its Compiler, Cambridge Univ. Press: Cambridge, 1979.
[Ritchie 78]
D. M. Ritchie, `UNIX: A Retrospective,' Bell Sys. Tech. J. 57 (6) (part 2), July-Aug, 1978.
[Ritchie 84]
D. M. Ritchie, `The Evolution of the UNIX Time-sharing System,' AT&T Bell Labs. Tech. J. 63 (8) (part 2), Oct. 1984.
[Ritchie 90]
D. M. Ritchie, `Variable-size arrays in C,' J. C Lang. Trans. 2 (2), Sept. 1990, pp. 81-86.
[Sethi 81]
R. Sethi, `Uniform syntax for type expressions and declarators,' Softw. Prac. and Exp. 11 (6), June 1981, pp. 623-628.
[Snyder 74]
A. Snyder, A Portable Compiler for the Language C, MIT: Cambridge, Mass., 1974.
[Stoy 72]
J. E. Stoy and C. Strachey, `OS6 - An experimental operating system for a small computer. Part I: General principles and structure,' Comp J. 15, (Aug. 1972), pp. 117-124.
[Stroustrup 86]
B. Stroustrup, The C++ Programming Language, Addison-Wesley: Reading, Mass., 1986. Second edition, 1991.
[Thacker 79]
C. P. Thacker, E. M. McCreight, B. W. Lampson, R. F. Sproull, D. R. Boggs, `Alto: A Personal Computer,' in Computer Structures: Principles and Examples, D. Sieworek, C. G. Bell, A. Newell, McGraw-Hill: New York, 1982.
[Thinking 90]
C* Programming Guide, Thinking Machines Corp.: Cambridge Mass., 1990.
[Thompson 69]
K. Thompson, `Bon - an Interactive Language,' undated AT&T Bell Laboratories internal memorandum (ca. 1969).
[Wijngaarden 75]
A. van Wijngaarden, B. J. Mailloux, J. E. Peck, C. H. Koster, M. Sintzoff, C. Lindsey, L. G. Meertens, R. G. Fisker, `Revised report on the algorithmic language Algol 68,' Acta Informatica 5, pp. 1-236.


Copyright © 1996 Lucent Technologies Inc. All rights reserved.