Cプログラミング言語が登場したとき、それは低レベル言語と見なされていましたか?


151

現在、C低レベル言語と見なされていますが、70年代に低レベル言語と見なされていましたか?この用語は当時も使用されていましたか?

多くの一般的な高レベル言語は80年代半ば以降まで存在しなかったため、低レベルの性質が長年にわたって変化したかどうか、どのように変化したかを知りたいです。


13
1978年頃の1つのデータポイントとして、一部のプログラミングメンターはCを美化されたアセンブリ言語として説明しました。
ベン・クローウェル

7
@BenCrowellあなたの声明の文脈で「栄光」が何を意味するのかわかりませんが、Cをユニバーサル(=プラットフォームに依存しない)アセンブリ言語と呼ぶことを経験しました。
メレビウス

13
興味深いことに、Cは低レベル言語ではなく、70年代よりも1つ少ないというケースがあります。これは、Cの抽象マシンがPDP-11からよりも現代のハードウェアからさらに離れているためです。
トム

5
これについて考えるとき、起源についても考えたいかもしれません。UnixはCで書かれており、cはUnix上で実行され、unixを他のプラットフォームにクロスコンパイルします。Unixをコンパイルするのに不要なものは不必要なオーバーヘッドであり、Cの主な目標は、コンパイラを可能な限り簡単に記述/移植できるようにすることでした。この目的のために、それは正確な正しいレベルだったので、私はCを高レベルまたは低レベルとは考えません。ほとんどすべてのUnixツールと同様に、多くの問題に非常に適応できるUnixを移植するツールだと思います。
ビルK

4
Lispは1958年
プライム

回答:


144

質問の歴史的側面に答えるには:

デザイン哲学は、あなたが聞いたかもしれない「K&R」であるブライアン・カーニガンとCデザイナーのデニス・リッチーによって書かれたCプログラミング言語で説明されています。初版の序文は言う

Cは「非常に高いレベル」の言語でも、「大きな」言語でもありません...

はじめに

Cは比較的「低レベル」な言語です... Cは、文字列、セット、リスト、配列などの複合オブジェクトを直接処理する操作を提供しません。配列全体または文字列全体を操作する操作はありません...

リストはテキストが続く前にしばらく続きます:

これらの機能の一部が存在しないことは重大な欠陥のように思えるかもしれませんが、...言語を控えめなサイズに抑えることには本当の利点があります。

(私は1988年の第2版しかありませんが、以下のコメントは、引用されたテキストが1978年の第1版と同じであることを示しています。)

ですから、はい、当時は「高レベル」と「低レベル」という用語が使用されていましたが、Cはその中間のスペクトルのどこかに位置するように設計されていました。ハードウェアプラットフォーム間で移植可能なCでコードを記述することが可能であり、それが言語が当時高レベルであると見なされたかどうかの主要な基準でした。ただし、Cには高水準言語の特徴であるいくつかの機能が欠けていたため、これは単純さを優先した設計上の決定でした。


42
これは素晴らしい答えです!検証可能な歴史的証拠+ OPが言及している期間の低レベルと高レベルの意味を最もよく知っている俳優の証言。ところで、引用はすでに1978年版にあったことを確認します。
クリストフ

157

これは、高水準言語と低水準言語の定義に依存します。Cが開発されたとき、アセンブリよりも高レベルなものはすべて高レベル言語と見なされていました。これはクリアすべき低いバーです。後に、この用語は、最近ではJavaでさえ低レベル言語であると考える人がいるという点に移行しました。

70年代の高レベルの言語環境内でさえ、Cがかなり低レベルであることを指摘する価値があります。C言語は基本的にBにシンプルな型システムを加えたものであり、Bはアセンブリに便利な手続き型/構造化構文層にすぎません。型システムは型付けされていないB言語の上に後付けされているため、一部の場所でintは型注釈を省略でき、想定されます。

Cは、その時点で既に確立されていた高価な機能や実装が困難な機能を意識的に除外しています。

  • 自動メモリ管理
  • ネストされた関数またはクロージャー
  • 基本的なOOPまたはコルーチン
  • より表現力豊かな型システム(例:範囲制限型、レコード型などのユーザー定義型、厳密な型付けなど)

Cにはいくつかの興味深い機能があります。

  • 再帰のサポート(すべての変数がグローバルライフタイムを持つ言語と比較して、スタックベースの自動変数の結果として)
  • 関数ポインタ
  • ユーザー定義のデータ型(構造体および共用体)は、Cの初期リリースの直後に実装されました。
  • Cの文字列表現(ポインターから文字)は、実際には、複数の文字を1つの機械語にエンコードするBに比べて大幅に改善されています。
  • Cのヘッダーファイルは、コンパイル単位を小さく保つための効率的なハックでしたが、偶然にも単純なモジュールシステムを提供していました。
  • より安全な参照と比較した、アセンブリスタイルの無制限のポインターとポインター演算。ポインターは本質的に安全ではない機能ですが、低レベルのプログラミングにも非常に便利です。

Cが開発された時点で、COBOL、Lisp、ALGOL(さまざまな方言)、PL / I、SNOBOL、Simula、Pascalなどの他の革新的な言語が既に公開されていた、および/または特定の問題領域で広く使用されていました。しかし、これらの既存の言語のほとんどは、メインフレームプログラミング用であるか、学術研究プロジェクトでした。たとえば、ALGOL-60がユニバーサルプログラミング言語として最初に設計されたとき、それを実装するために必要な技術とコンピューターサイエンスはまだ存在していませんでした。これらの一部(一部のALGOL方言、PL / I、Pascal)も低レベルのプログラミングを目的としていましたが、より複雑なコンパイラを使用する傾向があるか、安全すぎる(無制限のポインタがないなど)傾向がありました。Pascalは、可変長配列のサポートが特に不足しています。

これらの言語と比較して、Cは低レベルの開発により実用的であるために、「エレガントな」高価な機能を拒否しています。Cは主に言語設計研究プロジェクトではありませんでした。代わりに、比較的リソースが制約されたPDP-11ミニコンピューターでのUnixカーネル開発の派生物でした。そのニッチ(移植が容易なシングルパスコンパイラでUnixを書くためのミニマリストの低レベル言語)Cは絶対に優れています。45年以上経った今でも、システムプログラミングの共通語です。


17
既存のALGOLファミリとPascal言語に必要なものを知らない人のためのほんの小さな追加:これらの言語には、外部関数で宣言された(ローカル)変数にアクセスできる、字句的にネストされた関数がありました。外側のレキシカルスコープへのポインタの配列- -で、それはどちらかあなたが「表示」を維持しなければならなかったことを意味し、各関数呼び出しとリターン(字句レベルを変更) - またはあなたがチェーンレキシカルスコープにスタックして、そのような各変数のアクセスを持っていましたそれを見つけるためにスタックを複数の間接ホップする必要がありました。高価な!Cはそれをすべて放棄しました。まだ恋しい
-davidbak

12
@davidbak:x86-64 System V ABI(別名Linux / OS Xの呼び出し規則)は%r10、「静的チェーンポインター」として定義します。これはまさにあなたが話していることです。Cの場合、これは別の呼び出しで上書きされるスクラッチレジスタにすぎませんが、Pascalがそれを使用すると思います。(GNU Cネストされた関数は、あなたがそれに関数ポインタを加えた場合、このような機能は、インライン(例えばので、コンパイラは、スタック上のマシンコードのトランポリンを作成していない場合)は、外側のスコープへのポインタを渡すためにそれを使用します。定期の受容性をr10およびr11の使用法
ピーター

2
@PeterCordes魅力的です!Pascalは、System Vが登場したときにまだ広く使用されていました(正式なSysV ABIがいつ定義されたかはわかりませんが)。リンクされた回答は非常に有益です。
-davidbak

3
Cにはユーザー定義型(構造体/共用体)があります。これらの「機能」の残りは、言語をシンプルかつ表現力豊かに保つという目標を損なうため、ゼロまたはネガティブな使用のためです(難読化されたコードコンテストに参加している場合を除き:-)) 。
jamesqf

6
@jamesqf:しかし、ごく初期のCには構造体の割り当てがありませんでした。a = b;ISO C89でできるように構造体全体をコピーするのではなく、メンバーを個別にコピーまたはmemcpyする必要があると思います。したがって、初期のCでは、ユーザー定義型は間違いなく第2クラスであり、参照として関数引数としてのみ渡すことができました。 Cの配列に対する嫌悪感とC ++が構造体内の配列のメンバーごとの割り当てをサポートするのはなぜですか?
ピーター

37

1970年代初頭、Cは最新の構成要素を使用した新鮮な空気のまばゆい息吹でした。UNIXシステム全体をアセンブリ言語からCに書き換えても、スペースやパフォーマンスのペナルティはほとんどありません。当時、多くの同時代人がそれを高級言語と呼んでいました。

Cの著者、主にDennis Ritchieはより慎重であり、Bell System Technical Journalの記事で「Cはそれほど高度な言語ではない」と述べています。デニス・リッチーは、苦笑いして挑発的になるつもりで、低レベルの言語だと言います。Cの設計目標の中で最も重要だったのは、言語をマシンに近づけたまま、移植性、つまりマシンの独立性を提供することでした。

詳細については、元のBSTJの記事を参照してください。

ありがとうデニス。安心してお休みください。


3
基本的には、PDPアセンブリ用の型指定された構文ラッパーです。
アインポクルム


2
@einpoklum私はそれに同意する傾向があります。私は大学で1980年頃にPDP-11 / 34aでCを学びました。それはある教授によって「ポータブルアセンブリ言語」と言われていました。おそらく、PDP-11に加えて、Cコンパイラを使用できるSuperbrain CP / Mマシンがラボにいくつかあったためです。 en.wikipedia.org/wiki/Intertec_Superbrain
dgnuff

2
また、検証可能な歴史的証拠に基づいた優れた回答(すごい!K&Rの前バージョンがそこにありました!)。
クリストフ

7
@einpoklumこれはやや大げさではありませんか?アセンブラー(Z80およびM68K)、M(抽象的な16ビットのレジスターと命令セットを備えたPDP11構文)、およびCと呼ばれる「ポータブルアセンブラー」でCの80年代半ばにシステムとアプリケーションのコードを書く機会がありました。 、Cは間違いなく高レベル言語です。Cプログラミングの生産性は、アセンブラーよりも1桁も高かったです!もちろん、文字列(SNOBOL)、ネイティブデータファイルサポート(COBOL)、自己生成コード(LISP)、高度な数学(APL)、オブジェクト(SIMULA)はありません。したがって、それほど高くないことに同意できます
Christophe

21

このサイトの他の場所で書いたように、誰かがmalloc / freeメモリ管理パターンを「低レベルプログラミング」と呼んだとき、

「低レベル」の定義が時間とともにどのように変化するか面白い。私が最初にプログラミングを学んでいたとき、単純な割り当て/自由パターンを可能にする標準化されたヒープモデルを提供する言語は、実際に高レベルと見なされていました。では、低レベルのプログラミング、あなたは(!割り当てますが、メモリ位置そのものではない)、メモリの自分を追跡する必要があり、またはあなたが本当に空想感じていた場合は、独自のヒープアロケータを記述します。

コンテキストについては、これはCが出てからかなり後の90年代前半でした。


標準ライブラリは、80年代末の標準化以降のもの(既存のUnix APIに基づく)だけではありませんか?また、カーネルプログラミング(Cの元の問題ドメイン)は、当然、手動メモリ管理などの低レベルのものを必要とします。当時、Cは本格的なカーネルが記述された最高レベルのプログラミング言語であったに違いありません(最近ではNTカーネルもかなりの量のC ++を使用していると思います)。
アモン

6
@ hyde、1970年代にAlgol 60、2つの異なるFORTRAN方言、およびいくつかの異なるBASIC方言を使用しましたが、これらの言語にはポインターやヒープアロケーターがありませんでした。
ソロモンスロー

7
厳密に言えば、結果のメモリをmalloc()直接呼び出しbrk(2)たりmmap(2)、自分で管理したりすることで、noでプログラミングできます。これは考えられるメリットがない大規模なPITAです(たまたまmallocのようなものを実装している場合を除く)が、それはできます。
ケビン

1
@amon-ALGOLで下から上にプログラムされた注目に値するバロウズスタックベースのマシンを除く...そしてUnixよりもはるかに早い。ああ、ところで、Multics。これはUnixのインスピレーションでした。PL/ Iで書かれています。ALGOLと同様に、Cよりも高いレベル。
davidbak18年

6
実際、私たちの多くが今日Multicsを使用していない理由は、それが恐らく高価なメインフレームでしか実行されていないという事実と関係があるでしょう。セキュリティを備えた仮想メモリを実装するための専用ハードウェア。VAX-11のような32ビットミニコンピューターが登場したとき、銀行と政府を除くすべての人々がIBMとセブンドワーフから脱却し、大規模な処理を「ミニ」コンピューターに移しました。
-davidbak

15

多くの回答がすでに、「Cは高級言語ではない」などの初期の記事に言及しています。

しかし、私は積み重ねることに抵抗できません:当時、ほとんどまたはすべてではないにしても、多くのまたはすべてのHLL-Algol、Algol-60、PL / 1、Pascal-配列境界チェックと数値オーバーフロー検出を提供しました。

最後にバッファと整数のオーバーフローをチェックしましたが、これが多くのセキュリティ脆弱性の根本原因でした。...はい、それでも...

動的メモリ管理の状況はより複雑でしたが、それでもCスタイルのmalloc / freeはセキュリティの面で大きく後退しました。

したがって、HLLの定義に「多くの低レベルのバグを自動的に防止する」が含まれている場合、CとUNIXが発生していなければ、サイバーセキュリティの残念な状態は非常に異なっているでしょう。


7
私はたまたまインテルMPXの実装と、それがスピンアウトするポインター/バウンドチェックコンパイラーに関与していたので、パフォーマンスに関する論文を参照できます。基本的には5〜15%です。その多くは、1970年代と1980年代にはほとんど不可能だったコンパイラ分析を伴います-50%遅いかもしれない素朴なチェックと比較して。しかし、CとUNIXが20年までにこのような分析の作業をやめたと言ってもいいと思います。Cが最も人気のあるプログラミング言語になったとき、安全性に対する要求はずっと少なくなりました。
クレイジーグリュー

9
@jamesqfさらに、C以前の多くのマシンには、境界チェックと整数オーバーフローに対する特別なハードウェアサポートがありました。CはそのHWを使用しなかったため、最終的に廃止され、削除されました。
クレイジーグリュー

5
@jamesqfたとえば、MIPS RISC ISAはもともとPascalで記述されたスタンフォードベンチマークに基づいていましたが、後にCに移動しました。Pascalは符号付き整数オーバーフローをチェックしたため、ADDなどの命令でMIPSもチェックしました。2010年頃私はMIPSで働いていましたが、上司はMIPSr6の未使用の命令を削除したかったため、オーバーフローチェックはほとんど使用されなかったことが研究により示されました。しかし、Javascriptがそのようなチェックを行ったことが判明しましたが、OSのサポートが不足しているため、安価な指示を使用できませんでした。
クレイジーグリュー

3
@KrazyGlew-C / C ++では、符号付き整数オーバーフローによる「未定義の動作」をめぐるユーザーとコンパイラライター間の戦いが激化しており、今日のコンパイラライターが古い誤りを犯しているため、これを取り上げることは非常に興味深いことです。 「プログラムの悪化は罪ではありません」そしてそれを11に上げました
。stackoverflow

2
RustにCのようなSIMD組み込み関数がある場合、それはほぼ理想的な現代のポータブルアセンブリ言語である可能性があります。Cは、積極的なUBベースの最適化と、最新のCPUがサポートする新しいプリミティブ操作(popcnt、先頭/末尾のゼロをカウント、ビット反転、バイト反転、飽和など)数学)。Cコンパイラを取得して、HWサポートを備えたCPUで効率的なasmを作成するには、移植性のない組み込み関数が必要になることがよくあります。コンパイラーにpopcntをエミュレートせずにターゲットでエミュレートすることは、イディオム認識よりも優れていますpopcnt
ピーター

8

C(1972)より前の、以前のはるかに高い言語を検討してください。

Fortran-1957(Cよりも高レベルではない)

Lisp-1958

コボル-1959

Fortran IV-1961(Cよりもそれほど高くない)

PL / 1-1964

APL-1966

さらに、RPG(1959)などの中間レベルの言語は、ほとんどがプラグボードベースのユニットレコードシステムに代わるプログラミング言語です。

この観点からすると、Cは非常に低レベルの言語のように見え、当時メインフレームで使用されていたマクロアセンブラの少し上に過ぎません。IBMメインフレームの場合、データベースインターフェースがCobolに移植されていなかったため(当時)、アセンブリとIBMメインフレームで現在も使用されているCobolプログラム。


2
古い、より高い言語をリストしたい場合、LISPを忘れないでください
デュプリケータ

@Deduplicator-リストに追加しました。私はIBMメインフレームで使用されているものに焦点を当てていましたが、LISPがそれほど人気が​​あることは覚えていませんが、APLはIBMメインフレーム(タイムシェアリングコンソール経由)およびIBM 1130のニッチ言語でもありました。より多くのユニークな高級言語、例えばそれはAPLの現在のバージョンでライフゲームを作成するのにかかるどのように少しのコードを見て:youtube.com/watch?v=a9xAKttWgP4
rcgldr

2
少なくともCOBOL-85以前では、RPGまたはCOBOLを特に高レベルとは見なしません。COBOLの表面をスクラッチすると、本質的には非常に高度なアセンブラーマクロのコレクションであることがわかります。そもそも、関数、プロシージャ、再帰、およびあらゆる種類のスコープの両方が欠けています。すべてのストレージは、プログラムの先頭で宣言する必要があり、非常に長い序曲または痛みを伴う変数の再利用につながります。
idrougge

Fortran IVを使用したいくつかの悪い思い出がありますが、Cよりもかなり「高いレベル」であることを思い出しません
。– DaveG

@idrougge-COBOLおよびRPG、およびメインフレーム命令セットには、米国などの国の金融ソフトウェアの要件であるパックまたはアンパックBCDの完全サポートが含まれていました。「対応する移動」などの関連するネイティブ演算子は高レベルであると考えます。RPGは、生の入力フィールドとフォーマットされた出力フィールドおよび/またはアキュムレーターとの間のリンケージを指定しましたが、操作の順序ではなく、置き換えられたプラグボードプログラミングに似ているという点で異常でした。
rcgldr

6

あなたの質問に対する答えは、質問しているC言語に依存します。

Dennis Ritchieの1974 C Reference Manualで説明されている言語は、高レベル言語のプログラミングの利便性の一部を提供する低レベル言語でした。その言語から派生した方言は、同様に低レベルのプログラミング言語である傾向がありました。

ただし、1989/1990 C Standardが公開されたとき、実際のマシンのプログラミングで一般的になった低レベル言語については説明されていませんでしたが、代わりに-である可能性のある高レベル言語が説明されていました- -低レベルの用語で実装されています。

C Standardの作者が述べているように、この言語を便利にしたことの1つは、多くの実装を高レベルのアセンブラーとして扱うことができるということでした。Cは他の高レベル言語の代替としても使用され、多くのアプリケーションは高レベル言語ではできないことを行う能力を必要としないため、標準の作成者は実装が任意の方法で動作することを許可しましたプログラムが低レベルの構成を使用しようとした場合。したがって、C標準で記述されている言語は、決して低レベルのプログラミング言語ではありません。

この区別を理解するには、リッチーの言語とC89がコードスニペットをどのように表示するかを検討してください。

struct foo { int x,y; float z; } *p;
...
p[3].y+=1;

「char」が8ビット、「int」が16ビットビッグエンディアン、「float」が32ビットで、構造体に特別なパディングまたはアライメント要件がないプラットフォームでは、「struct foo」のサイズは8バイトです。

リッチーの言語では、最後のステートメントの動作は「p」に格納されたアドレスを取得し、それに3 * 8 + 2 [つまり26]バイトを追加し、そのアドレスと次のバイトから16ビット値をフェッチします、その値に1を追加し、その16ビット値を同じ2バイトに書き戻します。動作は、そこに格納されているオブジェクトの種類に関係なく、アドレスpのバイトに続く26バイト目と27バイト目に作用するものとして定義されます。

C標準で定義されている言語では、* pが「struct foo []」の要素を識別し、その後にそのタイプの少なくとも3つの完全な要素が続く場合、最後のステートメントはメンバーyに1を追加します* pの後の3番目の要素。他の状況では、標準によって動作が定義されません。

Ritchieの言語は低レベルのプログラミング言語でした。プログラマーは都合の良いときに配列や構造などの抽象化を使用できる一方で、メモリ内のオブジェクトの基本的なレイアウトに関する動作を定義したためです。対照的に、C89以降の標準で記述されている言語は、高レベルの抽象化に関して用語を定義し、それと一致するコードの動作のみを定義します。低レベルのプログラミングに適した高品質の実装は、標準で義務付けられているよりも多くの場合に有用に動作しますが、そのような目的に適した実装を行う必要があることを指定する「公式」ドキュメントはありません。

したがって、デニスリッチーが発明したC言語は低レベル言語であり、そのように認識されていました。ただし、C規格委員会によって考案された言語は、規格の指令を超える実装提供の保証がないため、決して低レベルの言語ではありませんでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.