Python開発者のためのC言語入門: プログラミングの深みにダイブ!
はじめに
どうも、私立YouTube高専、校長です。 本日は、「Python開発者のためのC言語入門: プログラミングの深みにダイブ!」 ということで、PythonからC言語への興奮溢れるステップアップについて解説したいと思います。 Pythonのシンプルでエレガントな世界から、C言語を通してプログラミングの深みへダイブしましょう。
そもそも、なぜ、Python開発者が、C言語を学習する必要があるのでしょうか? Pythonは万能な言語なので、今さらC言語なんて必要ないんじゃないか?と思うかもしれません。 しかし、そんなことはありません。 プログラミング言語には向き不向きがあります。 Pythonは高級言語として、非常に扱いやすい言語ではあるものの、問題解決の対象によっては、限界があります。
実際に、Pythonを動かすためのインタープリターとして代表的なcPythonはPythonではなく、C言語で実装されています。 Pythonで使われる、ライブラリも非常に多くのものがC言語や、それを拡張したC++言語で開発されているため、 プログラミングの深みにダイブする上では、C言語を避ける事はできません。
また、コンピューターを学習する上では、Pythonだけ学習しても、はっきり言って、コンピューターのことは全く理解できないでしょう。 なんだか、よくわからないが、文法通りにプログラムを書いたら、動いてくれるという程度の認識しか出来ないのではないのではないでしょうか。
それは、C言語で実装されたPythonインタープリターがコンピューターを高度に抽象化してくれているためです。 したがって、C言語の知識無くしては、このようなインタープリターの仕組みに由来する複雑な問題を解決する事もできません。
そこで、今回はPython開発者が、複雑な問題を解決できるようになったり、コンピューターの仕組みを理解できるようになったりするために、Python開発者がC言語を学習する意義、そして、Python開発者がC言語を学習する時に、躓きがちなことについて、解説したいと思います。
本日ご紹介するポイントに焦点を当てながら学習することで、PythonからC言語へのスムーズなステップアップが可能となります。
挑戦的でもありますが、新たな言語を学ぶことで、プログラミングの視野が広がるでしょう。
また今回ご紹介する情報以外にも、我々は、日本の技術者の技術力向上に向けて、 5年後も10年後も役立つ、有益な技術情報を日本語で分かりやすく発信しているので、 そういった動画を見逃したくない方は、今のうちにいいねとチャンネル登録しておいて貰えればと思います。
今後は、もっと組織化して、コンピュータ科学だけでなく、 古今東西あらゆる分野のテクノロジーを解説していきたいと思うので、 是非、応援よろしくお願いします。
C言語を学習する意義
それでは、まずは、Python開発者がC言語を学習する意義を理解する上で、どのような場合において、Pythonだと、限界が来るのかという事を、 PythonとC言語の、それぞれの使用例から読み解いていきましょう。 まずは、Pythonの使用例を、考えてみます。
Python
ウェブ開発:
Pythonはウェブ開発に使用することができます。 DjangoやFlaskなどのフレームワークを使ったウェブアプリケーション開発が非常に得意で、高い生産性が特徴です。 ハードウェアが高度に抽象化されており、コンピューターの仕組みを一々思い出さなくても、やりたいことが実現できます。
データサイエンスと機械学習:
また、Pythonはデータ解析、機械学習、人工知能などの分野で非常に広く使用されています。NumPy、Pandas、scikit-learnなどのライブラリが豊富であり、大規模なデータ処理が可能です。 データサイエンティストが良く使う言語ナンバーワンと言っても、過言ではないでしょう。
自動化:
また、システム管理やタスクの自動化を行う上で、Pythonは非常に便利です。多くのプラットフォームやファイル形式に対応したライブラリが無料で公開されており、シンプルな構文を使って、簡単に自動化スクリプトを書くことができます。
他にも、例を挙げれば、キリがないですが、ライブラリやフレームワークを活用したアプリケーションの開発が特徴的です。 次に、C言語の使用例を見てみましょう。いずれも、Pythonでは、出来ないことです。
C言語
カーネル開発: まずは、カーネル開発です。 C言語はメモリ空間に直接アクセスすることが可能であり、効率的なメモリ管理やハードウェア制御が可能であるため、 オペレーティングシステムのカーネルやドライバの開発に使用されます。 このような開発は、システムプログラミングと呼ばれることもあります。
Pythonは、ハードウェアが抽象化されてしまっているので、メモリ空間に直接アクセスする事ができません。 また、インタープリターの実装がOSありきなので、OSそのものを作るような、システムプログラミング言語として使用することは、不可能です。
組み込みシステム:
続いて、組み込みシステムです。
C言語で書かれたプログラムは、リソースが制限された環境でも動作させる事が可能なため、低コストや低消費電力が求められる場面で利用されます。 したがって、マイコンで動かすような組み込みソフトのプログラミングには、C言語が使用されます。
Pythonは、インタープリターの実装がOSありきなので、OSが動かないマイコンのような環境において、動かすことはできません。 MicroPythonというマイコンで動くランタイムもありますが、オーバーヘッドが大きく、計算資源を無駄遣いしてしまうので、組込みシステムで使用される事はほとんどありません。
高負荷処理:
次が、高負荷処理です。 C言語では、ハードウェアを適切に制御することで、計算資源を100%余すところなく、最適に使用することが可能です。 したがって、機械学習や数値計算のような、高い処理能力が要求される場面において使用されます。
Pythonでも、まったく同じ計算をすることは可能ですが、処理のオーバーヘッドが大きいため、計算の負荷がより重くなってしまいます。
PythonとCの使い分け
したがって、これらの特徴をまとめると、C言語はハードウェアに近い下回りの実装や、高い計算負荷を要求される実装に使われ、Pythonはそれをアプリケーションとして呼び出すラッパーとして使われます。
なぜかというと、例えば、Deep Learningの計算をC言語のみで実装することも可能ですが、Pythonのような、より高級な言語を使用することで、生産性を上げる事ができます。
負荷の重い部分さえ、C言語で実装すれば、処理速度も大きく低下することもありません。アムダールの法則と同じ原理です。
これが、Pythonの多くの計算ライブラリがC言語やC++言語で実装されている理由です。
Python開発者がC言語で躓きがちなこと
それでは、続いて、Python開発者がC言語を学習する際に、躓きやすい事柄について解説したいと思います。
これらの項目は、Pythonから始めた人には、非常に躓きやすいポイントだと思うので、重点的に、解説したいと思います。 ・実行の仕組み (インタープリター vs コンパイラ) ・型システム (静的 vs 動的) ・関数の引数(参照の値渡し vs 値渡し) ・メモリ管理とポインタ ・高水準な命令が使えない
実行の仕組み (インタープリター vs コンパイラ)
まず一つ目が、実行の仕組みです。 Pythonはインタプリタ型言語であるため、コンパイルが不要であり、インタープリターがソースコードを逐次解釈しながら、処理を行います。
一方、C言語はコンパイラ型言語であるため、実行前に、 ソースコードを機械語に変換することで、CPUが実行可能なファイルを予め生成します。 Windowsだと.exeという拡張子のファイルです。Linuxだと、ELF(Executable and Linkable Format)という形式のファイルです。
実行ファイルは、CPUが実行するべき命令が全て記述されています。 したがって、実行前に、CPUが実行すべき命令が決定しているというのが、Pythonとの大きな違いです。
このコンパイルを含む一連のプロセスを、ビルドと呼びます。 ビルドシステムは、makeやNinjaなど、様々なツールがあり、プロジェクトによって異なります。 ビルドは、プリプロセス、コンパイル・アセンブル・リンクと、色々な工程を経たうえで、機械語が生成されるので、どの工程で 不具合が発生したのかを、正確に推定できるようにならない限り、ビルドエラーを解決することができません。
最初のうちは、意味不明なエラーに戸惑いますが、ビルドの仕組みや実行の仕組みを学習することで、徐々にエラーを解決できるようになります。 最初は、セミコロンを忘れて、沢山エラーが出ると思いますが、是非エラー文をちゃんと読んで、調べてみてください。
型システム (静的 vs 動的)
次は、型システムです Pythonは動的型付け言語であり、変数の型が実行時に決まります。 例えば、ある変数に文字列を代入した後に、整数を代入する事が可能です。
対照的に、C言語は静的型付け言語であり、変数の型はビルド前に明示的に宣言します。 これにより、型に関するエラーをコンパイル時に検出できるため、安全性が向上します。
しかし、このような違いを理解せずに、Pythonと同じ感覚で変数を使うと、型チェックによるエラーやワーニングが出るので、C言語を書く時は型に注意して、プログラムを書く必要があります。
関数の引数(参照の値渡し vs 値渡し)
次は、関数の引数の渡し方の違いです。
Pythonしか書いたことがない人は、あまり意識していないかもしれませんが、Pythonにおける引数は、全てその変数を参照するための値を渡しています。 これを、参照の値渡しと言います。
一見、値渡しに感じる事もありますが、それは、Pythonはミュータブルオブジェクトとイミュータブルオブジェクトという2種類のオブジェクトがあるためです。
一方で、C言語では全て値渡しです。ただし、ポインタを使う事で、参照の値渡しのような事をする事も可能ですが、ポインタの値を渡しているだけなの、本質的には値渡しです。 このような違いを理解せずに、Pythonと同じ感覚で引数を使うと、意図した通りに動かないので、注意してください。
そもそも今の話が、何の話か理解していない方は、この機会に是非、引数が関数に渡される仕組みについて調べてみてください。 詳細は、今回の動画の範囲を超えるため、ここでは、省略しますが、リクエストがあれば紹介したいと思います。
メモリ管理とポインタ
次が、メモリ管理とポインタに関する話です。
Pythonでは、メモリ管理がインタープリターによって、自動で行われるため、メモリが完全に抽象化されており、開発者が意識的にメモリを確保・解放する必要がありません。
しかし、C言語ではメモリを自分で管理する必要があるため、メモリの確保や解放を行う明示的に行う必要があります。
ポインタというのは変数のメモリアドレスを格納するための変数で、これにより、メモリを直接制御することが可能になります。
C言語ではこのようにメモリを柔軟に制御することができるからこそ、ハードウェアを制御したり、メモリレベルの最適化をすることができるのです。
C言語では、ポインタを使いこなす事により、効率的なメモリ管理が可能ですが、使い慣れないうちはセグメンテーションフォルトやメモリリークなどの深刻なバグを作る可能性があります。そして、このような不具合は、使い慣れた後ですら、作りがちです。
ポインタは、Python開発者にとっては、非常にとっつきずらいポイントですが、ポインタに躓いた方は、以前に紹介した(動画)[https://www.youtube.com/watch?v=xAFhDak3Coc]があるので、是非そちらで、学習してください。
高水準な命令が使えない
最後が、言語として標準的に備えている命令の違いです。
Pythonでは、非常に高水準な命令を自分で定義することなく、使う事ができます。 例えば、文字列の操作では、+演算子を使う事によって、簡単に文字列の結合ができます。
一方、C言語では文字列を変数の配列として扱うため、メモリバッファの確保や結合を明示的に記述する必要があります。 特に、文字列の終端を示すナル文字('\0')には、注意が必要です。
Pythonのように最初から便利な命令が揃っている環境とは、全く異なるので、低水準な命令を使用して、プログラムを書く必要があることに注意してください。
逆に、C言語ではこのように低水準な命令を使用してプログラムを書くからこそ、ハードウェアレベルでの最適化が可能になるのです。
このような理由から、高度なアプリケーションをC言語のみで実装しようとすると、非常に生産性が低くなります。 処理速度と生産性のトレードオフが、プログラミング言語にはあることを覚えておきましょう。
おわりに
はい。それでは、以上が、Python開発者がC言語を学習する際に、躓きやすい事柄についての解説でした。 これらの違いが、PythonからC言語への移行において重要なポイントとなるでしょう。
もし、他にも、なにか躓いたとか、ここが良く分からないとかあれば、是非コメントで教えてください。
今回ご紹介した情報以外にも、我々は、日本の技術者の技術力向上に向けて、 5年後も10年後も役立つ、有益な技術情報を日本語で分かりやすく発信しているので、 そういった動画を見逃したくない方は、今のうちにいいねとチャンネル登録しておいて貰えればと思います。 コメントや拡散もして頂けると、非常にありがたいです。
今後は、もっと組織化して、コンピュータ科学だけでなく、 古今東西あらゆる分野のテクノロジーを解説していきたいと思うので、 是非、応援よろしくお願いします。
コメントも、非常に勉強になるので、是非よろしくお願いします。 是非一緒に、楽しいTech Lifeを過ごしましょう。
本日の動画の内容は以上になります。ここまでご視聴ありがとうございました。