Cプログラミング言語の性質

これはより大きいシリーズの一部です: “何かをプログラムする方法:Cプログラミング

序文

この記事では、「プログラミングクラッシュコース」の記事に言及し、情報を活用しています。 その記事の閲覧が推奨されます。

私が学んだ2番目のプログラミング言語はCです。 TRS-80 Color Computer II 16k(Tandy Radioshack製)が提供するBASICで歯を切った。 私のMacintosh IIsiが、私の父がインストールしたQuickBASICコンパイラ/インタプリタを持っていて、私の基本的なやり方を続けることができなかったのであれば、Pascalのような別のプログラミング言語が以前にあったでしょう。 私は単純なテキストの冒険から、トップダウンのロールプレイングゲームのための300 pgのマグナム・オパス(1週末に書かれた)、リアルタイムのサイド・スクローラー(これは 私が自分のコンピュータを手に入れるまでではなかったが、残念ながら私は弟のクアドラをしているだけでなく、技術仕様も覚えていないので、CodeWarriorに遭遇した(インストールした)。 さて、CodeWarriorでは、C、C ++、アセンブリを使用しました。 今私はビッグリーグのように!

私はプログラミングスタジオをアップグレードするのにも良い時期でした。なぜなら私が短期間で断続的に市立書店を訪れたとき(私は本屋がない半田舎の町に住んでいました) CおよびC ++。 これらにはゲームプログラミングウィザードの秘密などのMacintosh用のタイトルが含まれていました。 だから私はSystem 7、8、9のC言語をプログラミングし始めました(私はAppleのプログラマーでした)。これが関数、構造体、クラス、オブジェクト、ポインタ、アドレスなどの周りに頭を抱えていました。 私はいつも私のQuickBASICインストールにリンク可能なライブラリを作成したいと思っていました。(マニュアルは私がそれを行うことができると言っていました)Cでグラフィックスのような機械集中的なものをプログラムできますが、 決してそれを理解することはありません。 マニュアルはそれができると言いましたが、もちろんほとんど説明を与えませんでした。

BASICのような「高水準」の言語から、Cのような「低レベル」の言語に移行すると、実際にプログラミングしていたマシンの理解が深まり、プログラミングスキルが向上します。 。 今ではマシン全体にアクセスできました。基本的な通訳者がシステムツールボックスのどの部分を試してみるか決めただけでなく、私が望むものを実装できました。 より高いレベルの言語に固執するが、アルゴリズムやそのような一般的なマシンやコンピュータサイエンスについて学ぶことを望む人にとって、Cのような「中間レベル」の言語を学ぶことは必須である。 それは将来的に多くの扉を開くことができます。

Cはどこから来ますか?

Bell Labsと呼ばれる場所で働いていたデニス・リッチー(Dennis Ritchie)という男が、1969年から1973年の間にいつかCプログラミング言語として知られている種子を思いついた.Cは実際には数々の初期プログラミング他の言語はBPCLとBです。BPCL(Basic Combined Programming Language)は、1966年にケンブリッジ大学のMartin Richardsによって開発されました。当時の主な関心事は他のプログラミング言語用のコンパイラでした。実際、それは、 “brace programming”という概念を導入しました。これは、他の多くのプログラミング言語でも引き続き使用されています。 BCPLは、Ken ThompsonとDennis RitchieによってBell Labsで1969年頃に開発された、数値ではない再帰的なクロスマシンプログラムのための言語Bの開発に影響を与えました。

Cの歴史を知るためには、Unixオペレーティングシステムの初期の小さな歴史を実際に知ることができます。元のUnixオペレーティングシステムは、Dennis RitchieとKen Thompson(彼らは忙しかったのですか?)によってPDP-7でアセンブリ言語で実装されました.PDP-11が出てきたときに、システムを新しいマシンに移し、RitchieとThompsonはBを使って最初に考えましたが、Bは実際にPDP-11を利用するようには書かれていなかったので、これらの懸念に対処する新しい言語が登場しましたバイトをアドレス指定するこうして、Cは生き返った。おそらくCがBの後に来るので、Cはおそらく言語を与えられた名前でした。

コンパイル可能な言語として、CはVersion 2 Unixでデビューしました。すぐに1972年にUnixの大部分がCで書き直されました。面白いことに、Cは意図的に多くの異なるマシン上で実行可能に設計されていませんでしたが、 Unixの、そしてその容易さとシンプルさのために、それは多くの異なるマシン上で実行され始めました。 1973年までにC言語は十分な開発を楽しんでいたので、現在はほとんどのUnixオペレーティングシステムカーネル(オペレーティングシステムのコードの内部コア)を構成するのに十分強力です。 1977年頃、Ritchie氏とStephen Johnson氏はUnixオペレーティングシステムの導入を促進するために言語の開発を続けました.Johnsonは新しいマシンでCを使って開発するのを容易にする「ポータブルCコンパイラ」を作成しました。

1978年、RitchieとBrian KernighanはThe C Programming Languageの初版を出版しました(写真左)。これは実際に私が大学に通ったときのANSI Cプログラミングコースで私が “受けた”本でした。この本の第1版はANSI準拠ではありませんでした(少し説明されています)。標準が存在せず、非公式の仕様となっていたためです。このバージョンのCは、しばしば「K&R C」と呼ばれます。普及が始まったばかりのことは、いわば荒れ狂ったように広がっており、以来、メインフレームに打撃を与える最も普及して広く利用されているプログラミング言語の1つになっています。実際には、1989年のANSI(American National Standards Institute)がCの標準化版を作成して以来、標準化が国際標準化機構(ISO)によって採択されています。最初の標準では、K&R Cには存在しなかった多くの追加機能が実装され、非公式にC89と呼ばれました。本書は第2版で再び出版され、 “ANSI C”に準拠しています。 C89は、C ++標準が公式化された「基盤」または基礎として機能し、この標準は数年間比較的安定していました。それは1995年までであり、1990年の基準(C95として知られています)が修正され、いくつかの詳細が修正され、国際的な文字セットのサポートが追加されました。

これはCの話の終わりではありません。実際、この規格は1999年にさらに改訂されました。このバージョンは非公式にC99として知られるようになりました。それはまた3回修正されました。 C99には、インライン関数、複素数、可変長配列、柔軟な配列メンバー、最も注目すべき点として、1行のコメント(BCPLのように)が含まれています。 2007年には、2011年に出版された別のリビジョンから作業が始まりました。このバージョンはC11と呼ばれ、ジェネリックマクロ、匿名構造、アトミックオペレーションなどの新しい機能が追加されました。それぞれのバージョンは可能な限り下位互換性を追求しましたが、プログラムが必要な調整を行うためにどのバージョンが使用されているかをテストする方法が含まれています。

ここで特に注意すべきは、Cは組み込み環境でよく使われるということです。これは、GPIOピンなどのさまざまなハードウェアに直接アクセスできるマイクロコントローラまたは専用プロセッサの環境で実行するように、プログラムをコンパイルおよび書き込みすることを意味します。 Raspberry PIやArduinoのような普及した「組み込み」システムを考えるかもしれませんが、埋め込まれたものは、RTOS(リアルタイムオペレーティングシステム)を回路ボード上に「埋め込まれた」ものにするためのあらゆる種類のプロセッサを暗示することができます。しかし、固定小数点航空機、複数のメモリバンク、ハードウェアピンと割り込みへのアクセス、およびさまざまな異常なI / O操作を含むこれらのタイプのシステムでは、非標準的な要件(Cプログラミング言語標準に関して非標準)があります。これに対処するために、C Standards Committeeは、これらの共通の問題に対処する一連の言語拡張であるEmbedded Cと呼ばれるものを正式化しようとしました。

Cはあらゆる種類のアプリケーションで世界中で使用されている繁栄して生きている言語です。 アドレス、ビット、およびバイトを処理する能力を犠牲にすることなく、より抽象的な用語を使用して容易に組み立てることができます。 将来のCの成果と、次のバージョンでどのような改訂や拡張が行われるかを見ていきます。

C言語と他の言語との関係

Cは中間レベルの言語であり、高級言語の最高の要素と低レベルの言語の最高の要素を組み合わせたものです。言語の「レベル」は、言語の質を反映するものではなく、言語が多かれ少なかれ強力であり、使用がより容易で難しいということを意味しません。これは、言語のプログラミングのプロセスで利用される抽象化の反映です。私はこれが何を意味するのかを説明します。

たとえば、アセンブリのような低レベル言語を取る。この考え方では、プロセッサを使って直接プログラムし、サイクル、レジスタ、アドレスを制御します。ちょっとずつ注意深くシャトルされます。アセンブリーのような問題、プロセッサー・コマンドのためのニーモニック以外の真の抽象化を欠いていること、大きなものや微妙なものはすべての種類の索引、ジャンプ、および理解しにくいアルゴリズムで扱いにくくなります。また、特定のプロセッサと密接に連携することの副作用として、最終的なプログラムは他のプロセッサアーキテクチャへの移植性に欠けます。

BASIC(私のような)のような高水準の言語を試してみてください。あなたはもはやそれぞれの小さなビットとバイトを動かすのではなく、代わりに変数、配列、カプセル化されたフロー制御(命令型プログラミングに関する私のプログラミングクラッシュコースの記事を参照してください)、そして非常に抽象的な方法を実行する方法について話します。さらに、これらの抽象メソッドはプログラムされているため、他のプラットフォーム用にプログラミングすることができ、コード自体をそれらのプラットフォームに移植することができます。しかし、いくつかの点では、プログラムが各バイトの動きを具体化することなく解決しようとしている問題に近づくことはできますが、望むときにはプロセッサの制御レベルを達成できません。

中間レベルの言語を入力してください:プログラムの抽象度を高め(変数、データ型、フロー制御を使用)、簡単でシンプルですが、柔軟で強力なレンダリングを行うより詳細なビットにアクセスして制御できます)をアセンブリのようなものとして扱います。その上、少し慎重な準備で、Cは他のマシンに簡単に移植できます。これは、Cプログラミング言語の力の多くがある場所です。

Cは何をしますか?

Cプログラミング言語の基本的な概念は、関数の概念です。 Cの関数機能により、プログラマーは、アルゴリズムや命令の一部を、他のコードとは別に、独自の入力と出力、および独自の変数を使用して独自のチャンクにカプセル化することができます。基本的に1つの関数は理想的には別の関数の動作に影響を与えません。そのため、いくつかの解決策に向けて一緒に働くことができるミニプログラムを本質的に書くことができます。一番重要なのは、機能が何であるかを知っていれば、それがどのようにプログラムされているかを必ずしも知らなくても使えるということです。これは、コードのセクションを共有し、コードを再利用することとして知られています。このような区画化を実装する言語(Cなど)は、構造化言語として知られています。対照的に、構造化された言語は、コードの一部がいつでも影響を与える可能性があるため、非常に揮発性であり、機能的なカプセル化の考え方に反するため、グローバル変数などの概念の使用を妨げます。ある関数は、間接的に他の関数の状態や演算に影響を与えます。同様に、ジャンプコマンド(BASICからgotoとして知られている)の使用は、厳密に禁止されているか、または推奨されていません。 1つのランダムなコードまたは機能から別の機能にジャンプすると、プログラムフローが中断され、互換性に悪影響を及ぼします。プログラムのある部分から別の部分に移動するには、関数呼び出しのゲートウェイを経由する必要があります。ちなみに、これらの関数とその “ゲートウェイ”のコレクションは、インターフェイスと呼ばれます。

注:より小さい規模の構造化では、コードブロックとして知られるものを通しても構造化が行われます。 これらは、ループやif節などの中かっこで囲まれたステートメントです。 これらは、ブロック内のすべての文が一緒に(線形に)実行されるという意味で、コードの単位として扱われます。

Cではif-clause、whileループ、forループなどの多くのフロー制御文で命令型プログラミングの共通部分を使用できます。しかし、より多くのインポートのポインタとアドレスのシステムです。 Cは、通常の可変アクセスなどの値としてデータの一部を参照するか、そのデータのメモリアドレスを参照できるようにする2つの演算子を使用します。データのメモリアドレスを参照する変数は、Cのポインタと呼ばれます。Cのポインタとアドレッシングシステムは、すぐに単純で複雑なものです。それはどのように設計されているのか(私の意見では)通常は現実世界のプログラミングで使用されます。このメモリ操作システムは、Cに「低レベル」の能力と、場合によってはアセンブリプログラミングと比較される能力の一部を提供します。

Cが知っているもう一つのことは、強いデータ型の欠如です。つまり、Cが変数にデータ型を採用しているということです(クラッシュコースのデータ型から変数が保持できる変数の種類を覚えていれば、これらのデータ型を操作に強制しません)。たとえば、Cでは、整数、文字、浮動小数点型の変数をすべて同じ数式で使用できます。これは暗黙の型変換と呼ばれるものによって達成されます。 Cをコンパイルするとき、コンパイラは異種のデータ型を計算のために必要な形式に変換します。場合によっては、引数に定義するデータ型とは異なるデータ型を関数に渡すこともできます.Cはデータ型を自動的に変換して適合させます。

Cもやや簡潔な言語です。私が言いたいのは、C言語のほうがはるかに少ない数のキーワード(言語の一部としてコンパイラによって解釈される文字列)を多くの他の言語よりも利用しているということです。 C89は32個のキーワードを使用し、C99は5個を追加し、C11はわずか数個を追加します。比較のポイントとしてのBASICは50以上のキーワードを持つことができます。

Cは何をしないのですか?

暗黙の型変換のため、Cは変数、関数、および式の間の厳密な型の互換性を必要としません。同様に、「実世界のプログラマー」による使用の影響により、プログラマーは自分が望むやり方をすることができます。これは、ランタイムエラーチェックのように、高水準言語で当然とられるものがCに存在しないことを意味します。これは、プログラムの実行中に潜在的なエラーチェックが行われないことを意味します。これは、実際には、配列の境界がオーバーランしていないこと、型変換が悪意がないこと、何も指していないポインタやゴミが使用されていないことなどを知らせるチェックや通知がないことにつながります。これはプログラマの責任ですプログラムを書く。フルタイムのプロのプログラマーとして働いていたとき、ヌルポインターが私のプログラムのseg-faultを何度引き起こしたかは分かりません。

Cは、(与えられたプログラムが実行されている間は)ガベージコレクションのようなリアルタイムの処理を実行しません。 Pythonのような多くの高水準言語では、インタプリタ(別のポストでコンパイラとインタプリタの違いを扱います)はC言語で書かれています。データオブジェクトは変数の他の部分で参照されなくなるまでメモリに保存されますプログラムで。その後、それらは自動的にメモリから簡潔に削除されます。プログラマは何もする必要はありません。これは自動ガーベジコレクションと呼ばれ、JavaScript、Java、Pythonなど、さまざまな言語に対応しています。 Cはメモリの直接的な操作を可能にし、「プログラマーのやり方から抜ける」ため、プログラマーは独自のガベージコレクション手段を提供する必要があります。プログラマが自分自身を解放するまで、メモリは使用されたままです。

結論:Cに影響を与えたのは何ですか?

Cはプログラマー向けに作成されました。これは重複しているように見えるかもしれませんが、Cの作成時には、コンピュータに何をすべきかを伝える技術者以外の人の悩みを軽減するために、多くの言語が作成されていました。あなたが考えることができるほぼすべてのフィールドについて素敵なユーザーインターフェイスですべてをラップした洗練されたエンドユーザープログラムは、まだ存在しませんでした。多くの場合、コンピュータを使用することは、あなたが望むことをするためにプログラミングすることを意味し、これにもかかわらず、このタスクを達成するために必要な多くの非技術的な人々がいました。 BASIC、PASCAL、COBOLなどの言語は、この難しさを緩和するために考案されました。たとえばBASICやCOBOLは、高度に技術的な人たちによって使用されるようには設計されていませんでした。彼らは、コンピュータをプログラミングする作業のプロセスを改善するために、ほとんど何もしませんでした。それらは、プログラマでない人がコンピュータがすべきことを定義できるように設計されています。

Cは、高度に技術的なことをしたいプログラマによるアセンブリプログラミングの海から作られました。これは、プロのプログラマが既に実世界に従事しているプロセスを改善することを意味していました。アセンブリプログラミングの頭痛のない、アセンブリプログラミングでできることと同じ種類のものを実現するために、はるかに高速で信頼性の高い方法を意味しました。実際、C言語はアセンブリ言語の代わりに使用できますが、アセンブリ言語の力で、成功への大きな鍵でした。

初期の段階では、高度に技術的な目的を達成するためにC社が採用されました。つまり、特にオペレーティングシステムとメインフレーム制御システムのプログラミングです。これらのタイプのプログラムは、プロセスをスケジュールし、メモリを非常に密接に扱い、他のプログラムにサポートサービスを提供し、一般的にアセンブリレベルのマシンアクセスが必要です。 Cのアセンブリとの互換性、そして実際に構造化された言語であるCの面でのアセンブリより優れているため、これらのフィールドはかなり改善されました。

今日では、多くの人々がより高いレベルの言語でかなり多くを達成することができ、多くの人々は、アクセシビリティのためにCのような中間レベルの言語の代わりにそれらを使用します。最近のマシンでは、Cのような言語を使って、PythonやJavaScriptなどの高級言語がC言語と同じような多くのことを達成できる非常に洗練されたオペレーティングシステム環境を構築しています。また、組み込みプロセッサやマイクロコントローラの分野でも、その実用化は今でも実りあります。オペレーティングシステム全体を提供するシングルボードコンピュータがあり、PythonやJavaScript(Raspberry PiやBeagleBoneなど)の機能を提供していますが、提供されているようなARM組み込みプロセッサボードが数多くありますそれらを制御するためにCの使用を必要とするテキサス・インスツルメンツの商標です。これらのボードには、裸のボーンRTOS(リアルタイムオペレーティングシステム)があり、プログラマは特定の回路を完全に制御することができます。 Cは、より洗練されたアクセシブルなプログラミングの仕組みには十分にお金をかけていましたが、同時に、低レベルのプログラミング作業のためにここに滞在しています。アセンブリからほぼ一歩離れているので、それは志望プログラマーが学びマスターするための優れた言語です。

これはより大きいシリーズの一部です: “何かをプログラムする方法:Cプログラミング

この記事が好きだったら、私のパトリオンで私をサポートすることを検討するかもしれません。

毎月の約束が大丈夫なら大丈夫です。コーヒーを買うことをお勧めします。

photo credit: Ubahnverleih RoboCup 2016 Leipzig – Debugging via photopin (license)

Liked it? Take a second to support kadar on Patreon!

あわせて読みたい

コメントを残す

%d人のブロガーが「いいね」をつけました。