以下、推測が入っています。間違い等があればご指摘下さい。
初期のCが開発されたのは1972年です。当時は今よりもパーサ(構文を解析するプログラム)について今ほど発展はしておらず、また、最初のCのコンパイラはC以外で作る必要がありました。ただ、かなり初期にセルフホスティングコンパイラはできていた模様です。しかし、C自体がまだ貧弱であり、コンパイラを作るにも限界がありました。
初期のCコンパイラ: mortdeus/legacy-cc - GitHub
紹介文: 本の虫: デニス・リッチーによって書かれた最初のCコンパイラーがGitHubで公開
何を言いたいかというと、Cはなるべく構文を単純かつ機械的に処理できるようにする必要があったと言うことです。;
で文の終了が明示しなければならなかったり、コメントは/* */
しか使えなかったり(いまは//
も使える)など現代の言語に比べると機械的に処理しやすいかが重点に置かれています。
さて、この初期のCにはプリプロセッサがありません。コンパイラ部分はなるべく単純にしたかったため、他のファイルを見に行くという処理をコンパイラにさせることが難しかったのだと思われます。そこで、プリプロセッサという全く別の機能をCに追加することで、他ファイルの読み込み、つまり、ヘッダファイルの読み込みというものの考え方を導入しました。
プリプロセッサは単純な文字列の置換です。いえ、当時の技術では単純な文字列の置換しかできなかったのです。#include
で分離したヘッダファイルをその部分に置換することはできるようになりましたが、その方法は原始的で、本当に単純に置換するだけです。そして、どのファイルを既に読み込んだのかと言うことをプリプロセッサで記録しながら進めると言うことを実装することすらできませんでした。そのため、二重インクリュード問題が発生することになります。そこで考えられたのが、#ifndef
等による分岐でのインクリュードガードだったと思われます。
その後CはANSIやISOの規格(C89/C90)になり、最新はC11です。ANSIである程度整理されましたが、最新C11であっても、この単純な仕組みは維持された形になっています。また、現代でもC89/C90で書かれたプログラムが残っているため、いますぐ無くなることはないでしょう。
なお、現代のコンパイラはかなり発展しており、当時のプリプロセッサができなかったすでに読み込んだファイルを覚えておくと言うことはできるようになっています。非標準の方法ですが#pragma once
を使うと、インクリュードは一度のみになります。メジャーなほぼ全てのコンパイラで対応済みですので、現代のコンパイラができないと言うことではありません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。