C言語とC++のメリット・デメリットを比較してみた。

C/C++

はじめに

プロジェクトの一部をC#からC言語、もしくはC++に移行することになり、どちらに移行するかを決めるためにメリット・デメリットを比較してみました。私の調査は主にWiki、Microsoft Learn、ChatGPT、各言語のリファレンスサイトなどの情報と、実際に実装してみての主観に基づいて書いています。

C言語のメリット・デメリット

メリット

コードが古くなることがない

C言語はバージョン更新がほとんどなく、フレームワークがないので「C言語=どの時代の人間が書いても同じ」というのは意外と強いです。
更新頻度が高い言語では、数年前のコードは古くなっていき、同じ言語でも全く違った書き方になっていたりするため、最新バージョンに関しての有識者が集まりづらかったります。

覚えることが少ない

C言語はフレームワークがなく、コードで使える構文やライブラリが少ないので、覚えること自体は少ないです。それでも機能としては難しいポインタやメモリ管理があります。

コンパイラに悩むことが少ない

これもバージョン更新が少ないことに起因していますが、どのコンパイラがどのバージョンに対応しているなど考慮することがなく、C言語用のコンパイラなら基本どれでもコンパイルできる。

基本的に軽量で高速

オブジェクト指向言語と比べて、クラスなどの概念がない分、動作中に確保しなければいけないメモリは少なくなる傾向があります。組み込み開発でリソースが限られているなど、環境的制約に対して強いです。

デメリット

メモリ管理に人的リソースを割きすぎる

メモリ操作に関するバグは静的解析は発見できず、実行して初めてわかるもの。この種のエラーはメモリへの書き込み側の問題か、メモリ確保側の問題かを切り分ける必要があり、影響範囲の特定が難しいためデバッグが困難になります。
そもそもメモリ管理自体が、人間にとって直観的ではないため、脳のリソースが必要以上に割かれることになる。

文字列操作が弱い

C言語ではstring型をサポートしないため、char型の配列、もしくはcharポインタを使って管理する必要があります。string型と比べるとかなり煩雑なプログラムになるため、文字列操作が多いシステムでは苦しいことになります。

オブジェクト指向ではない

オブジェクト指向の恩恵をここでは語りませんが、巨大で複雑な仕様をシステムで表現する際にオブジェクト指向を使わずにやろうとすると、複雑さに負けて、いわゆるスパゲティコードになっていくことが想定されます。構造化プログラミングでも、規約を設けて複雑さに対抗する術はありますが、限界があります。組み込みシステムがそこまで巨大で複雑になることは少ないと思うので、そういった意味ではやはり組み込みには向いている言語といえます。

ライブラリが貧弱

これは覚えることが少ないという意味ではメリットですが、他の言語では当たり前に標準ライブラリにあるような機能すら、C言語ではサポートしていません。そして、オープンソースライブラリも基本的にないので、自作するというのが基本です。私が調べたところ、csvやjsonの読み込み、Loggerなど、一般的に使いそうなライブラリはC言語ではありませんでした。確かにjsonはオブジェクト指向ならではなので、ないのも納得ですが、csvやLoggerくらいはあってもいいんじゃないかと思ってます。

エラーハンドリングが困難

C言語ではtry-catchのように内部で発生したエラーをキャッチする仕組みはないため、すべての関数が責任を持ってエラー内容を呼び出し元へ伝える必要があります。C言語の関数は戻り値を1つしか持てないため、戻り値にエラー内容を割り当てると、本来返したい数値や配列が返せなくなってしまいます。そこでC言語ではエラーメッセージやエラーコードを戻り値に設定し、その代わりに関数の引数に本来の戻り値を入れるための箱をポインタで渡して(参照渡し)、それを書き換えることで複数の戻り値を実現してたりします。
そうして、関数呼び出し後は戻り値のエラーコードを確認してエラーの発生が確認できれば、さらに上の呼び出し元へそのエラーコードを返していきます(人力)

モダン言語とスタイルが離れすぎている

これもバージョン更新が少ないことに起因していますが、最近の言語のほとんどはオブジェクト指向をサポートし、GCCやジェネリクスなどの概念をサポートしているのに対し、C言語は構造化プログラミングやポインタといったスタイルを取ります。このスタイルが離れすぎたスタイルは、C言語プログラマが将来的に悪い意味で希少的存在になっていく可能性が高いです。最近ではRUSTのようなモダン言語のスタイルを取り込みつつ、組み込み開発にも向いた言語が登場しているため、C言語開発者がより希少性を増していく可能性があると思います。

C++のメリット・デメリット

メリット

バージョンが更新され続けている

C言語とは真逆で現在C++は3年に一度更新されています。(C++17、C++20、C++23)
これによってC++はモダン言語で良しとされる概念を取り入れていっているため、年々、表現力が増しています。例えばC++11ではラムダ式、C++14では型推論、C++17ではbyte型などが追加されています。仮にC++をやってこなかったとしても、オブジェクト指向言語であれば、同じような表現がC++でもできるようになっています。ただしC++の場合は表現力が高すぎて(オプションが多すぎて)、それが逆に複雑になっている面もあります。

ライブラリが豊富

C++には標準でSTL(Standard Template Library)というものが存在します。実はC++はプリミティブ型としてstringが用意されているわけではなく、STLの中にstringというクラスが存在します。こんな感じでSTLがC++で不便なところ補ってくれています。
その他にもオープンソースのライブラリがgithubに豊富にあります。

オブジェクト指向

C++はオブジェクト指向言語のため、巨大で複雑な仕様にも対応しやすいです。DIやレイヤー化アーキテクチャなど、システム構築に役立つ様々な手法が取れます。

メモリ管理する場面が、C言語ほどない

C++ではstringのサポートによって、文字列操作で直接メモリにアクセスするような書き方は多くありません。ファイル操作についてもstreamがサポートされてます。ただそれ以外でもメモリを確保する場面はありますし、確保したメモリは解放しなければメモリリークしてしまいます。ただC++ではスマートポインタというSTLの機能を使って、メモリ管理を多少ですが簡略できたりします。

エラーハンドリングが容易

C++ではtry-catch構文がサポートされているため、エラーハンドリングはモダン言語の容易行えます。これによりC言語のようなエラー内容を呼び出し側へ橋渡しを続けるようなこともなく実装できます。

デメリット

習得コストが高い

C++は「C言語 + 拡張構文 + ライブラリ + オブジェクト指向」のような言語なので、C言語に比べて習得コストが高いです。その他の言語と同じような機能でも、C++では特殊な書き方をする必要があったりと、他の言語からの参入者にとっても習得コストが高いと思います。例えば、関数スコープの定義や、ラムダ式のスコープの定義、参照か値渡しかの選択など。性能面を上げるための書き方や、リソース消費を抑えるための関数など、細かいところに手が届くような言語のため、混乱を招きやすいです。
あとはC言語と同じで、多くはないとは言え、ポインタとメモリ管理の概念を抑えることは必須になります。

C言語よりリソース消費量は多い

オブジェクト指向のサポートにより、メモリとして確保しなければいけない情報が増えるため、基本的にC言語よりリソース消費量は多いです。組み込み開発のようなリソースが限られた開発においては、C++よりC言語の方が優れている場面があります。

標準ライブラリや構文の意図がわかりずらい

モダンなプログラミングスタイルでは、関数は関数名・引数などで詳細をうまく表現し、副作用がないことで詳細を知らずに扱えるようにすることが一般的です。
C++の標準関数を見てみるとわかりますが、副作用は少ないですが、関数名・引数では詳細は伝わってこないことがほとんどです。つまりリファレンスを見ないと扱えないです。
例えば、getlineという関数がありますが、パッと見て、streamから1行読み込むのかなというところまでは伝わるかと思います。そこまでは良いのですが。。

stringstream textStream(line);
string line;
bool result = getline(textStream, line); // streamから1行読み込む OK

bool result = getline(textStream, line, ","); // streamから最初のカンマまでを読み込む Why?

1つ目のgetlineはいいですね、まだ直観的だと思います。(string line = textStream.readline()だったらエクセレントですが)
2つ目のgetlineは良くないですね。lineとは行。つまり改行コードまでを指す言葉なので、文字が指定できるならreadToTarget(対象まで読む)とかじゃないと意味が通りませんね。getlineなのに、lineが返ってこないとなってしまいます。

こういった一つ一つの関数を取ってみてもコストが高いと思います。

項目別評価

C言語C++備考
習得コスト×どちらも簡単とは言えないが、C言語の方がシンプル。
運用環境のリソース消費C++もリソース消費が大きいわけではないが、C言語に比べると劣る傾向がある
メンテナンス性×OOPやライブラリの恩恵が大きいが、C++でもメモリ管理は必要だし、煩雑な構文をメンテナンスしていく必要がある。
大規模・複雑なシステム×OOPの恩恵が大きい

総評

リソースが限られている組み込み開発で、規模が小~中程度で、シンプルな仕様ならC言語が良いかなと思いました。大規模な組み込み開発で、リソースに余裕があるなら、C++よりJavaとかの方がいいんじゃないかなと思います。
じゃあC++はどこで使うのという話ですが。リソースが限られいて、大規模で複雑なゲーム開発が向いてるのかな。

C++が拡張言語だからC言語に優れているということもなく、プロジェクトの状況に応じて判断する必要があります。

おわりに


今回まとめて思ったことは、C言語もC++も性能を売りにしているだけあって、人間にとっては難しい言語だということですね。C言語はあれで完成している気がするので、バージョンアップが入らないのもある程度、納得しました。無理に構文を増やす必要もないと。

C++に関して個人的に思ったのは、バージョンを上げるなら構文を増やすのではなく、減らすことを考えたほうが良いということ。意味(セマンティック)に対して構文(シンタックス)が多すぎるのは、表現力というより、散らかっていると感じます。もちろん非推奨になっていった機能はあるのですが、対応が緩やかすぎると感じます。おそらくコンパイラのメンテナンス団体と、言語仕様策定団体が別なので、大きい変更ができないしがらみもあるのかなと思いますが。
モダン言語を参考にしていても、モダン言語に追いつけない言語と感じました。

タイトルとURLをコピーしました