C++の市場性
いわゆる業務系のシステム開発者にとって、C++はなじみの少ない言語でしょうし、実際のところ、あまり使用されていないと思います。現在C++が使用されているのは、サーバー系のソフトウェアやミドルウェア、OS、パッケージソフトウェア、組込ソフトウェアなどです(図3)。
サーバー系のソフトウェア/ミドルウェア/OS関係
C++は、本来OSを開発するために作られたC言語を基にして開発された言語なので、生成されるコードの実行効率が良いだけでなく、細かいメモリ操作も可能です。しかもC言語との親和性が高いので、C言語で開発されたミドルウェアやOSを、非常に拡張しやすい言語となっています。実際にLinuxやApacheなど、C言語で記述されたOSやサーバーソフトにおいても、最近の機能拡張部分ではC++がよく使われています。
パッケージソフトウェア関係
各社から、さまざまなプログラミング言語の開発環境が提供されていますが、これらの多くは、対応する言語を問わずC++で書かれてます。その他にも、ワープロソフト、表計算ソフト、グループウェアなど、多くの領域のソフトウェアがC++で開発されています。
組込ソフトの領域
組込ソフトの世界では、コードの実行効率がとても重視されます。そのため1980年代まではアセンブラが主流でした。1990年代に入り、複雑な組込ソフトの領域から徐々にC言語へと移行が進み、現在では組込ソフト資産の多くはC言語に置き換わっています。もちろん小さいソフトでは、いまだにアセンブラが多いと思いますが、比較的規模の大きい組込ソフトではC言語が採用されています。現在は、これまで作ってきた組込ソフトの資産を活かしてオブジェクト指向に取り組んでいく活動が、各開発現場で進んでいます。その際に、C言語との親和性の高いC++が採用されるケースが多くなっています。進んでいる企業においては、既にC++で組込ソフトが開発されていますし、その他の企業においても、おそらくはC++での開発が主流になるものと思われます。私たちもC言語からC++への移行について相談を受けるケースが増えています。
C++の開発者の実態
前述したC++の適用領域のいずれにおいても、不具合に対して極めて敏感な領域であると言えます。ところがC++は、不用意にコードを書いてしまうと、検出するのが難しい不具合を作りこんでしまう危険性があります。残念ながら、これは自由度の高いC++の副作用とも言えるものです。
私たちは、中途採用などで多くの開発者とお会いしておりますが、やはり危ないコードを平気でいてしまう方が多く見受けられます。もちろん優れた開発者も多いとは思いますが、あいまいな知識で実装すると陥ってしまう罠は、たくさん転がっています。以降では、これらの罠について実例を交えながら述べたいと思います。
C++の配列
そもそも、C/C++の配列について正しい知識を持っているプログラマは、どのくらい存在するのでしょうか。以下のCのプログラムをご覧ください。
#include <stdio.h> void reverseHello(const char src[], char dst[]) { int i, j; for (i = 0, j = 0; i < 5; i++, j--){ i[dst] = src[j]; /* A */ } } int main(void) { char hello[] = "Hello"; char buf[6] = {'\0','\0','\0','\0','\0','\0'}; reverseHello(&hello[4], buf); printf("%s\n", buf); return 0; }
非常にわざとらしい処理となっていますが、この処理を実行すると、何のエラーも発生せずに正常終了します。
olleH
さて、上記プログラムに関する次の質問に回答できるでしょうか?
- コメントAにおける
i[dst]
という書き方が、なぜ成立するのか - コメントAにおける
src[j]
はj
が負となるが、なぜ不正アクセスにならないのか reverseHello
関数の引数src
、dst
は配列か
1.と2.は、配列の全てを理解していなくても'[ ]
'が演算子であることを知っていれば、容易に回答が想像できるかと思います。
- 1.は、配列添字演算子は二項演算子で、左辺と右辺の前後の位置関係を問わないので、
i[dst]
のような記述でも正常にコンパイルできます。 - 2.は、
src
はmain
関数で宣言される配列buf
の5番目の要素へのポインタを指していることを考えれば、buf
の1番目の要素へのポインタまで、つまりj
が-4までは問題なくアクセス可能です。 - 3.は、配列が引数になり得ないことを知っているかどうかがポイントです。配列の'
[]
'を使って宣言しているものの、src
とdst
は、配列ではなく変数(ポインタ)であり、実際に関数内の演算によって値を変更することも可能です。
読者の皆様は、全て回答することができたでしょうか。上記の事象を知っていることに価値があるかどうかはともかく、これらは通常プログラマが持っていて然るべき言語仕様の基礎知識です。しかしながら、実際にすべての質問に回答できたプログラマは、1割にも満たないのではないでしょうか。宣言・式・演算子などは入門書でもあまり詳しく解説されていないことや、これらの詳細を理解していなくても、とりあえず動くプログラムが作れてしまうことなどが、基礎知識の欠落の原因となっているのではないかと思います。