お気楽C言語プログラミング超入門のフォントを Web フォント (Noto Sans JP, Noto Sans Mono) に変更し、印刷用の CSS を追加しました。Web ブラウザの印刷機能を使って PDF に変換することもできます。表示が崩れるときはフォント Noto Sans Mono CJK JP をインストールしてください。
『お気楽C言語プログラミング超入門』は M.Hiroi が Linux でC言語を再学習するために作成したページです。入門講座の体裁をとってはいますが、かけ足で進めていくつもりなので、すこし勾配の急な再入門的な内容になる予定です。プログラミング経験がない方にはちょっと難しいかもしれません。M.Hiroi のサビついた腕をどこまでブラッシュアップできるかわかりませんが、興味のある方はお付き合いくださいませ。
C言語は 1972 年 AT&T ベル研究所の D.M.リッチー氏によって UNIX という OS を開発するために作られたプログラミング言語です。OS というシステムソフトウェアを開発するために設計されているので、アセンブラのような低水準に近い操作が可能になっています。このため、C言語は汎用アセンブラとか高級アセンブラといわれることもあります。
ほかの高水準言語とは違い、C言語は配列の範囲やオーバーフローなどのチェックは行っていません。また、「ポインタ」の使い方を誤れば、プログラムは簡単に暴走してしまいます。それでも、コンパクトで高速なマシン語が出力されることと、拡張性や保守性の点ではアセンブラよりも断然優れていることから、C言語は広く普及するようになりました。たいていの環境でC言語を利用することができます。
プログラミング言語はプログラムを実行する方法によって、コンパイラとインタプリタという 2 つの方法に分けることができます。一般に、C言語はコンパイラ型のプログラミング言語に分類されますが、インタプリタ型のC言語もあります。以前、ROOT: analyzing petabytes of data, scientifically. では、後藤正治さんが開発された C/C++ インタープリタ CINT が使われていましたが、現在では Cling という C++ インタプリタに置き換えられたようです。
Unix 系 OS の場合、標準のCコンパイラに cc がありますが、ほとんどのディストリビューションで GCC (GNU Compiler Collection) が同梱されています。Linux のように、コマンド cc が gcc になっている OS もあります。最近は Clang というコンパイラも使われるようになってきました。Clang - Wikipedia によると、Clang は 『GNUコンパイラコレクション (GCC) を置き換えることのできるコンパイラを提供すること』 を目標にしていて、GCC よりもコンパイルが速く、エラーやワーニングのメッセージがわかりやすいといわれています。
M.Hiroi は Clang に興味があるので、本稿ではCコンパイラに Clang を使ってC言語の学習を進めることにします。Debian 系の OS であれば、次のコマンドで Clang をインストールすることができます。
sudo apt intstall clang
$ clang --version Ubuntu clang version 14.0.0-1ubuntu1 Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin
コマンドは gcc のかわりに clang を使います。なお、Clang は Cygwin でも利用することができます。setup-x86_64.exe で簡単にインストールすることができるので、Cygwin ユーザーで興味のある方は試してみてください。
C言語でプログラムを作る場合、エディタを使ってソースファイルを作成します。ソースファイルとは、プログラミング言語で記述された命令書のことです。この命令書をコンピュータが理解できるようにマシン語に変換する必要があります。
コンパイラは、ソースファイルを実行ファイルに変換します。一度変換してしまえば、あとは外部コマンドと同様にそのプログラムを実行することができます。それでは、標準的なC言語を例に実行ファイルができるまでの様子を見てみましょう。
いきなりソースファイルを実行ファイルに変換することはできません。まず、ソースファイルをアセンブラプログラムに変換します。この作業をコンパイルといいます。そして、この作業を行うプログラムをコンパイラといいます。C言語で書かれたプログラムは、Cコンパイラによって変換されます。ほかのプログラミング言語のコンパイラを使うことはできません。
Unix 系 OS で標準的なCコンパイラを使用する場合、ここの処理は cpp と cc1 が担当します。C言語のソースファイルは、拡張子に .c が使われます。ソースファイル abc.c はコンパイラによって abc.s というアセンブラプログラムに変換されます。Unix 系 OS の場合、アセンブルプログラムの拡張子は .s が使用されます。このとき、ソースファイルのほかにも「ヘッダファイル」という複数のファイル ( *.h ) が必要になります。
次に、アセンブラプログラムをオブジェクトファイルに変換します。この作業をアセンブルといい、それを実行するプログラムをアセンブラといいます。Unix 系 OS では as が担当します。
オブジェクトファイルの内容はマシン語なのですが、このままでは実行することができません。オブジェクトファイルを実行ファイルに変換する作業がリンクです。そして、この作業を行うプログラムがリンカと呼ばれます。Unix 系 OS では ld が担当します。オブジェクトファイルの拡張子は .o です。リンク作業は、「ライブラリ」という複数のオブジェクトをまとめたファイルの中から、必要なオブジェクトを取り出し [*1]、abc.o と一緒に結合して abc という実行ファイルを作ります。
このように、実行ファイルに変換するまで、複数のプログラムを使います。いちいち手作業でこれらのプログラムを実行するのでは疲れてしまいますね。そこで、必要なプログラムを順番に呼び出してくれる「コンパイラ・ドライバ」というプログラムが用意されています。これが cc です。GCC であればコマンド gcc を使い、Clang であれば clang を使います。
$ clang -o abc abc.c
上記のように入力するだけで、abc.c は abc という実行ファイルに変換されます。この様子を見ただけでは、アセンブラやリンカが働いていることはわかりません。clang がソースファイルを実行ファイルに変換するように見えますが、今まで説明したように、複数のプログラムが働いているのです。なお、「コンパイルする」というと、一般には、ソースファイルから実行ファイルに変換する作業すべてを指す場合が多いようです。
それでは実際にコンパイルしてみましょう。次のプログラムは画面に hello, world と表示します。
リスト : hello.c #include <stdio.h> int main(void) { printf("hello, world\n"); return 0; }
$ clang -o hello hello.c $ ls hello hello.c $ ./hello hello, world
-o は実行ファイル名を指定するオプションです。-o を省略すると実行ファイル名は a.out になります。
それでは、お馴染みの「たらいまわし関数」を使って、gcc と clang の実行時間を計測してみましょう。C言語の場合、たらいまわし関数は次のようになります。
リスト : たらいまわし関数 #include <stdio.h> int tak(int x, int y, int z) { if (x <= y) { return z; } else { return tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y)); } } int main(void) { printf("%d\n", tak(24, 12, 0)); return 0; }
時間計測はコマンド time を使います。time で時間を計測する場合、プログラムの起動時間も含まれることに注意してください。実行結果は次のようになりました。
$ gcc --version gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ gcc -O2 -o takg tak.c $ clang -O2 -o takc tak.c $ time ./takg 1 real 0m7.695s user 0m7.694s sys 0m0.000s $ time ./takc 1 real 0m7.534s user 0m7.524s sys 0m0.010s
最適化のオプションはどちらも -O2 を指定しました。Clang のほうがちょっとだけ速いみたいです。興味のある方はいろいろ試してみてください。
『お気楽C言語プログラミング超入門』の著作権は筆者「広井誠 (Makoto Hiroi)」が保持します。無断使用や無断転載は禁止いたします。『お気楽C言語プログラミング超入門』で作成したプログラムはフリーソフトウェアとします。ご自由にお使いください。プログラムの改造や配布もご自由にどうぞ。その際は出典を明記してくださるようお願いいたします。
ただし、ドキュメントの内容とプログラムは無保証であり、利用したことにより生じた損害について、作者「広井誠 (Makoto Hiroi)」は一切の責任を負いません。また、これらのプログラムを販売することで利益を得るといった商行為は禁止いたします。