第6回では,Linux上で標準的に使われるコンパイラ「GCC」の基本的な使い方を紹介しました。今回は,より詳しい使い方を説明します。

 「第6回 LinuxでC/C++言語のコンパイルを試す」では,gccコマンドやg++コマンドによる必要最小限の手順を見てきました。これらのコマンドを含むコンパイラ・プログラムは,GCC(GNU Compiler Collection)と呼ばれます。GCCは元々,GNU C Compilerの略称だったのですが,現在ではCollectionというだけあって,C++,Objective-C,FORTRAN,Javaなどのコンパイラも含まれています。ここでは,gccコマンドをもう少し詳しく見ていきましょう。

 おさらいになりますが,gccコマンドの書式は,次の通りです。

 gcc [オプション] <ソースコード名>

先に紹介した-oオプションは,出力ファイル名を指定するオプションです。これ以外にも様々なオプションがあります。gccのmanマニュアルには膨大なオプションが紹介されていますが,代表的なものを表1に示します。

表1●gccコマンドの主なオプション
表1●gccコマンドの主なオプション

 -cオプションは,ソースコードのコンパイルとオブジェクトコードの生成までを実行するオプションです。

 $ gcc -c hello.c

を実行すると,hello.oというオブジェクトファイルができあがります。逆アセンブルしてファイルの内容を見てみましょう(図1)。

図1●objdumpコマンドを使った逆アセンブルの例
図1●objdumpコマンドを使った逆アセンブルの例
[画像のクリックで拡大表示]

 LinuxなどのUNIX系OSでは,オブジェクトファイルや実行形式のファイルにおいて,ELF(Executable and Linking Format)というフォーマットが広く採用されています。オブジェクト・ファイルの冒頭に,「file format elf32-i386」とあるのが確認できます。

 ELF形式のファイルは,いくつかのセクションに分かれています。機械語のコードが格納されるのは,textセクションです。2行目に「section .text」とありますね。「00000000 <main>:」以下の行は,main関数内の処理が書かれています。左から,相対アドレス,機械語の16進コード,ニーモニック(アセンブリ言語)が記されています。

 このオブジェクトファイルから実行ファイルを生成するときには,

 $ gcc -o hello hello.o

と入力します。出力ファイル名を指定しなければ,そのファイル名はa.outとなります。

 次に,最適化オプション-O(大文字のO)を紹介します。-Oもしくは-O1を指定すると,オブジェクトコードのサイズと実行時間を減らすように最適化を行います。-O2,-O3を指定すると,さらに最適化のレベルが上がります。小さなプログラムでは差が出にくいですが,プログラムによっては体感できるほど実行時間に差が出ることもあります。

 なお,-Osを指定すると,実行時間よりもオブジェクトコードのサイズ削減を優先して最適化を行います。

 -l(小文字のL)は,リンクするライブラリを指定するオプションです。例えば,数値演算ライブラリlibmをリンクするときは,次のようにします。-lオプションの直後に「lib」を外して指定する点に注意してください。「-llibm」のように指定するとエラーになってしまいます。

 $ gcc -lm -o hello hello.c

 -gオプションを付けると,デバッグ情報が実行ファイルに埋め込まれます。Linuxでは,GDB(GNU Debugger)というデバッガを使ってデバッグができます。GDBを使う際は,-gオプションを付けてコンパイルします。-gオプションを付けないと,デバッガの中で変数名や行番号が表示されないので,デバッグがやりにくくなります。また,デバッグをするときは,最適化オプションは指定しないようにします。

 -Wallオプションを付けると,すべての警告メッセージが表示されるようになります。このオプションは推奨されているので,できれば常に付けて実行するとよいでしょう。例えば,宣言されているのにプログラム中で使用されていないような変数があると,次のような警告メッセージが表示されます。

 hello.c:5: warning: unused variable 'a'