PCにLinuxをインストールするとPythonは使用できるのですが、環境によっては、gccなどがインストールされていない場合があります。C言語を使用する場合には、gccをインストールすることになりますが、C++を使用する際にはg++をインストールする必要があります。
g++がインストールされている場合、
のようにmanページの表示のコマンドを打ち込むと
のような表示になります。インストールされていない場合には、エラーメッセージが出てインストールのコマンドが表示されるので、それを打ち込むとインストールを行うことが出来ます。この際に、パスワードを使用してインストールを行うことになりますが、その後はインストーラーの流れに沿ってインストールを行うことになります。
インストールの有無は、
■ manページの表示
■ バージョンの表示
のコマンドで確認できるのですが、インストールされていない場合には、
のよなエラーがでます。エラーの下部には、
のようなコマンドが表示されるので、これに準じてインストールをすることになります。
プログラミング言語と仕組み
C言語では、<stdio.h>と言う標準ヘッダーファイルを読み込んで、I/Oが使用できるようにしてヘッダーファイル内に収録されている関数を使用する仕組みになっていますが、これを使用すると組み込み関数レベルの事が出来ます。
Pythonでは、組み込み関数を使用する場合には、収録されている物をそのまま使用できますが、C言語では
■ stdio.hをincludeする
■ main関数を用意する
■ main関数の中に処理を実装する
と言う流れになっていました。コンパイル型言語の多くは、このような仕組みになっているので、PythonやJavaScriptのようなスクリプト言語のように何も記述せずに動くというものではなく、
【 使用するものを事前に用意する 】
仕組みになっています。この際に、
【 動かすものの仕組みの指定 】
を行うので、
■ 道具箱から道具を出す
■ 処理を塊で管理する
ような構造になっています。その為、関数という塊の中に処理を実装するような仕組みになっているわけですが、この仕組みに準じて記述を行うと
■ コード内で使用するものを読み込む
■ 関数という構造の中に処理を実装する
と言う作りになっています。その為、 【 処理の説明などで使用するコメント 】 などは処理に関係ないのですが、それ以外のものには処理を行うためのものになっています。
プログラミング言語を使用する場合には、最初にディスプレイへの印字を行うので、 【 Hello,World! 】 の文字を表示する方法を学習しますが、C言語の場合だと、
画像
のようなコードを書いて、コンパイルして実行することになります。
C++はC言語をオブジェクト指向にして使いやすくしたものになりますから、構造は似ていますが、同じ処理を行う場合でも異なる記述になります。
Pythonなどのように実行環境で実行するような仕様の場合、コンパイルという概念がないので、コードの実行時にユーザーがコンパイルの処理を行うことはありません。これは、Java Scriptも同じですが、こうした言語でもJITコンパイラーが動いてる場合もありますし、Pythonだと外部ライブラリを使用する時にキャッシュファイルを使用するようなコードを書くとCPythonでコンパイルしたpycファイルが生成されるので、BASICとは全く異なる処理が行われています。
これに対し、コンパイル型言語は、実行可能な実行ファイルを生成するので、
■ コーディング
■ ビルド
と言う作業が発生します。PythonやJavaScriptの場合だとコーディング後はそのまま実行できますが、これは、テキストファイルの状態を実行環境が処理をしているので、コードが実行される仕組みになっています。
これに対し、コンパイル型言語の場合だと、実行可能な状態のものを作って実行することになりますから、機械語の状態になった実行ファイルを生成する必要があります。
この時に行うのがビルドの処理になります。ビルドはコマンドを実行してコンピューター上で実行ファイルを生成する処理になりますが、この際に、1つのファイルだけで完結するようなものだとコンパイラーでそのまま実行すれば良いのですが、ライブラリを使用する際には、
■ 動的ライブラリ
■ 静的ライブラリ
があるので、これを含めてコンパイルを行う場合には、リンカを使用して関連付けヲ刷る必要があります。その為、ビルドの際には
■ コンパイラ
■ リンカ
を使用してビルドを行っているわけですが、この時に使用するのが、プログラミング言語で使用するコンパイラになります。
このビルドの処理を行うことで実行ファイルが生成されますが、コンパイル型言語は 【 ネイティブ型 】 になりますから、この場合、
■ アーキテクチャ
■ OS
が異なると、異なる実行ファイルが生成されます。
つまり、WINDOWS環境で実行ファイルを生成した場合にはWINDOWSでしか動作しませんから、アプリケーションレイヤーソフト(エミュレーター)を使用して動作させないと動かすことが出来ません。
その為、同じソースコードをビルドを行ったとしてもLinuxとWINDOWSでは全く違う物が出来上がります。
この辺りは、
■ Linuxのネイティブ環境
■ CygwinでLinuxコマンドを使った環境
で作業をしてみると確認が出来ますが、現在のWINDOWS環境だと、WSL2が使用できるので、
■ WSL2@Linux
■ WINDOWS@Cygwin
という環境を構築して同じC++のコードをビルドすると、WINDOWS環境だとa.exeが出来上がると思いますが、Linux環境だとa.outが生成されます。
このように明らかに違うものが出来上がりますが、現在は、こうした物もWINDOWS環境だけで対応できるようになっています。
基本的にコンパイル型言語の場合はネイティブなので、上記のようにアーキテクチャとOSの種類が異なると異なる実行ファイルが生成されますが、仮想型のようにプラットフォーム依存がないものもあります。
1995年に登場したJAVA言語は、JAVA VMという仮想マシンを用意してこのVM用の命令セットなどを用意することで、バイトコードを実行することで処理が出来るようになっています。その為、JAVAの場合、
■ JDK : コンパイラ
■ JRE : ランタイム
をインストールして使用します。プログラミング言語の場合、
■ コーディング環境
■ 実行環境
を用意することになりますが、JAVAの場合だと、このような形になっています。これがVMを仲介して動作させる仕組みになっていますが、マイクロソフトの.NETもそういった仕様になっています。.NET6以降は統一されているので、.NETを使用すると、.NET上で動作するので、同じコードを異なる環境でコンパイルしてもVM用の物が出来上がりますから問題なく使用できるのですが、WINDOWS環境だとネイティブ環境のように.exeの形で実行ファイルが生成されるので誤認してしまうことがありますが、.NETは、実行ファイル内に命令セットとVMが包含されているだけなので、種類としてはJAVAと同じく仮想型のコンパイル型言語になります。
その為、 VisualStudio や VisualSrudio Code を使用してC#のコードをコンパイルした場合、.exeノカタチの実行ファイルが出来上がると思いますが、このファイルはネイティブではなく内部にVMと命令セットを包含したものになっています。
C言語はC++は、ネイティブなので、実行環境とビルド環境を合わせる必要がありますが、これを回避する時にクロス開発を行うことになります。
また、Flutterのように一つのコードでクロスプラットフォーム用にビルド出来るもの(Pythonでも使用できるライブラリが存在します。)もありますが、ネイティブの環境で最適化したほうが高速になる場合があります。
C++の場合
C++はC言語同様にネイティブ型なので、ビルドをする環境によって実行ファイルが異なります。プログラミング言語ですから、
■ コーディング環境
■ コンパイラー
を最初に用意しておくことになります。
と言っても、サーバOSのようなCUI環境でもコーディングとビルドはできるので、
■ VIM
■ g++
だけ用意しておけば、学習を始めることが出来ます。
デスクトップOSの場合だと、統合開発環境を用意すると作業がしやすいのですが、Linux環境だとターミナルだけでも作業を行うことが出来ます。
現在のターミナルは 【 分割表示 】 が可能なので、
■ カレントディレクトリの表示
■ VIM
■ ターミナル
の表示が出来ますから、
■ ファイル表示
■ コーディング
■ ビルド&デバッグ
を行うことが出来ます。この分割表示をした状態をGUI環境で扱いやすくしたものが、Visual Studio Codeなどの統合開発環境になります。
最初にg++をインストールしておくとビルドは可能なので、簡素なコードを書きながらC++の実行ファイルの生成までの作業を行うことが出来ます。
この時に標準実装のテキストエディタを使用するKTも出来ますが、現在の殆どのエディタで色分けができるようになっているので、
のように色々と間違ったものでも修正すると
のようになります。
C++でのHello,World!
プログラミング言語の学習を行うと、最初に表示を行う方法を学習します。C++はコンパイル型言語ですから、Pythonのように最初からターミナルで組み込み関数を使用した作業を行うことは出来ませんから、コードを書いてビルドを刷る作業からスタートすることになります。
殆どの事例で
■ 構造を覚える
■ 表示を行う
を最初に行うことになりますが、此の時に使用されるコードが 【 Hello,World! 】 の表示になります。Pythonだと、 【 print('Hello,World!') 】 のように組み込み関数に収録されているprint関数の引数に文字列を追加するだけで大丈夫ですが、C++の場合だと、
この仕組みですが、
のようにC++ではstdioではなく、ストリームを読み込むことになるので、 【 iostream 】 を読み込むことになります。そして、
のようにC言語と同様にmain関数を用意します。C言語と同様に 【 型 】 を指定することになりますが、
のように引数を格納する()があり、{}の中に処理を実装することになります。確か、情報Iだと関数辺りまでは扱うことになっているはずですが、基本的な関数の考え方はPythonと同じです。関数の範囲は{}で指定することになるので、このコードでは、
の範囲が実行される処理になります。これをブロックといいますが、現在のプログラミング言語だと、
■ ループ
■ 分岐
■ 関数
■ クラス
などでこうした構造を用いることになります。
この関数の中に表示を行う記述を刷ることになりますが、この時に、少し特殊な記述を行うことになります。
表示を行う部分は、
の部分になりますが、表示を行う場合には、
を用いることになります。これは、stdと言うネームスペースがあり、その中のcoutを使用していることになります。
その為、 【 std 】 の中の 【 cout 】 を使用するので、その処理を行うために、 【 :: 】 を使うことになります。この時の 【 :: 】 をスコープ解決演算子と言います。
この記述を行うと表示が出来るわけですが、
と言う文字列を表示する際には、処理との関連付けをする必要があります。この場合、
を使用して
を行うことになるりますが、C++の場合だと、
のような不等号を使用します。これを処理を行う対象物に対して指定する仕様になっています。
表示を行う場合には、coutを使用するので、
のような形になります。このコードでは、
をその後に追加していますが、これは、
【 改行してバッファをフラッシュする 】
という処理になります。これを行うと、\nとは異なる形で改行を実装できます。C言語と同様に改行を行う際には
を使用しますが、これを使用することで1つの処理の塊の終点を指定することが出来ます。
C言語もそうですが、関数を使用する際には戻り値を出力する必要があるので、処理の後には
を追加することになります。
コードをビルドする
エディタを使用して
のようなコードを書いた場合、C++のコードとして保存する必要があるので、拡張子を 【 .cpp 】 にして保存をします。
そうすることで、g++を使用してコードのビルドを行うことが出来ます。g++がインストールされている環境だと
のように 【 g++ ファイル名.cpp 】 でビルドが出来ます。この際に、cdコマンドでファイルのある場所に移動しておく必要がありますが、カレントディレクトリでこのコマンドを実行するとコードに問題がなければ実行ファイルが生成されます。Visual Studio Codeなどのエディタの場合、最初にプロジェクトを保存するので、その場所をカレントディレクトリとして作業を行えるので、F5キーでデバッグを行うと、そのままビルドが実行されるようになっていますが、ターミナルで作業をした場合には、ホームフォルダーからスタートすることになるので、VIMなどでターミナルの指定をしておかないと少し煩雑な処理が発生します。
このコマンドだとカレントディレクトリに実行ファイルが生成されるので、
のようにlsコマンドを使用すると、
のようにコードの1.cppとビルド済みのa.outが生成されていることが確認できます。
ビルド済みの実行ファイルを実行する場合には、C言語と同様に
で実行できるので、実行すると
のようにcoutを使用して指定した文字列を表示することが出来ます。C言語では、
【 gcc ファイル名.c -o 変更後のファイル名.拡張子 】
のでファイルのリネームを行いますが、C++の場合だと
のように、
【 g++ -o 変更後のファイル名.拡張子 ファイル名.cpp 】
のような形になります。このコマンドでビルドを行うと実行ファイルが生成されるので、lsコマンドで確認してみると
のようにtestのファイルが追加されています。a.outでビルドを行うと、ビルドするたびにファイルが上書きされるので、ビルドする際には常にリネームを行うことになります。これを
のように実行してもコードは同じなので
のように同じ結果になります。
iosteam.h
C++では、coutを使用しますが、C言語で使用するstdio.hを使用することも出来ます。
コードを書く場合には、
■ 処理
■ return 0
の構造にしなければならないので
のような問題があるコードだとエラーがでます。これは構造もそうですが、引用符にも問題があるのですが、C++でも
を読み込んで
のようにprintf関数を使用できます。これだと【 ; 】が抜けているので、
にして、
のようにしてビルドを行おうとしても
のようにエラーがでます。この部分だけでなくC言語と同様にC++でも引用符は型で使い分ける仕様になっているので、
のように引用符の問題が指摘されています。このようにコードに問題があれば、ビルド時にエラーメッセージが出て問題点(これは、構文エラー)が指摘されルシ用になっていますが、処理に問題がある場合にもエラーメッセージが表示されます。
これを修正して
のようなコードにして、
のように引用符と順番を入れ替えて
のようにコードをビルドします。lsコマンドで確認すると
のようにカレントディレクトリにファイルが追加されているので、
のように実行してみると、
のようにprintfの部分が表示されません。
このようにコードを書いても仕様と異なることを行うと意図した結果にならないので、
【 エラーはでないが異なる処理になる 】
ことがあります。これは順序の問題なので、
のようなコードにして
のようにprintfの処理をストリーミングの前に持ってきて
のようにビルドを行い、
のようにカレントディレクトリにある実行ファイルを
のように実行すると
のようにstdio.hを読み込んでprintf関数を使用することも出来ます。
ただし、正規表記は 【 std::cout 】 なので、C言語のような記述をすることはありません。
この辺りは、ストリームの記述が便利なので比較してみると正規の表記のほうが扱いやすいのでC言語とは異なる表記を用いることになります。
C++を使う場合
LinuxでC++を使用する際には、g++のインストールがされていることが前提になりますが、複雑なコンパイルの指定になる場合だとMAKEファイルを作ることになります。その為、プログラミング言語の使い方を覚えた後に別の物を覚えることになります。
この辺りは、現在の情報IでもPythonを使用する際に外部ライブラリを使用するのでプログラミング言語以外のものを学ぶ必要がある事を体験刷ると思いますが、どのプログラミング言語でも目的によって異なる知識が必要になる場合があります。
今回は、
■ 構文エラー
■ エラーがでないが異なる挙動になる事例
を紹介しましたが、プログラミングを行うと、前者の状態は修正が効くので問題がありませんが、後者の場合だと動作した上で問題が出るので、他の処理に関連する(連動や参照の関係にあるもの)場合だと、予期せぬ挙動が広範囲で発生し、問題の発生源を探すのが困難になります。
こうした問題がでないように知識をつけておく必要があるわけですが、 【 コピー&ペースト 】 でコードを丸写ししただけだと、 【 使用している環境で動作するのかどうか疑わしい場合もでてくる 】 ので、コードを書く場合には 【 確実に動作するものを使用する 】 必要があります。
この辺りは学習の初期段階だと殆ど発生しない問題になりますが、複雑なコードを書く場合や、外部ライブラリ参照のコードを書く場合だと、条件を知ってから設計を行わなければなりません。
そのため、知識がない状態でコードのコピー&ペーストだけでアプリケーションを作る状態だと 【 複雑な処理になると動作しないものが出来上がる可能性が高い 】 ので、基礎から理解しておく必要があるわけです。
処理についてはエラーが出る程度だと問題点が見えているので特に問題がないのですが、今回のように意図しない挙動になるものが出ることのほうが問題になります。
プログラミング言語を使用してコーディングを行う場合、
【 構文的に問題がない処理的に間違ったもの 】
だとごく当たり前に実行されてしまうので、そうならないように設計を刷る必要がありますが、知識がないとこの問題のFIX ができませんから、間違ったコードの状態で放置するしかなくなります。そうなると、まともなものを作ることは不可能になるので、完成する前にプロジェクトが頓挫することになります。
これは、動くのを作る時全般に言える事ですが、設計したものが意図した挙動と異なる動きになる場合があります。
その場合には修正を刷る必要がでてきますが、コーディングを行う場合にはコードの修正の作業になります。その場合、実装されている挙動の確認を行うことになりますから、処理の実行と操作を行って確認することになります。
数値の変化だけだとデバッグ用の表示機能を用意して変数の変化などを表示する方法もありますが、パフォーマンスを確認する場合だとシステムの情報を見る必要もでてきます。
コーディングを行う場合、簡素な処理で学習を行うだけであれば性能が低めなものでも大丈夫ですが、プログラミング言語を使用したコーディングはコードの実行が大前提になっているので、PCの構成を考える場合には
【 作ったものが意図した速度で動作する事 】
を前提で考えていくことになります。その為、ギガスクール構想のPCだと教師あり学習を行うと現実味のない時間がかかることがありますし、シェーダーを使用した表示関連だと出来ないことのほうが多いです。
この辺りは、ゲームエンジンを使う場合も同じですが、この場合だと 【 制作するものが動くこと 】 を前提に構成を考えていくことになります。
この時に予算の上限が発生するはずですから、個人の場合だと予算似合わせた構成を考えることになります。
ちなみに、エンドユーザーのコンテンツを見ると言う処理はラスターグラフィックの再生なので、デコード処理しか行っていないので、制作用途で必要はスペックとは異なります。ゲームの場合だと素材の制作+システムの制作になりますが、 【 最高品質で動くことを確認しておく必要がある 】 のでその性能の環境を用意しておく必要があります。
コーディングは手段なので、実際に使用するのは完成品になりますから、
■ 動作確認
■ デバッグ作業
■ パフォーマンス調整
を行う際に意図したものが作れるものを用意しておく必要があります。
今回の作業はAtom D510で行っていますが、この辺りの簡素な処理だと現在のアーキテクチャであればビルドも一瞬で終わると思います。