C言語は1972年にAT&Tベル研究所のカーニハンとリッチーによって開発された、システム記述用のコンパイラ型言語です。かの有名なUNIXと呼ばれるOSをはじめ、多くのOSやシステムの開発に利用されています。比較的古い言語でありながらいまだ現役のプログラミング言語であり、またCを基礎としオブジェクト指向という概念を取り入れたC++やC#などのように発展させたものも含め、現在のプログラミング言語のスタンダードとしての地位を守り続けています。
1989年に機能が改良・拡張された標準規格がANSIによって制定され、ANSI-Cとして広まっています。
(※ ) UNIXは最初違う言語で記述されていましたが、後にC言語で書き直されています
C言語の特徴は、書き方が簡単に表現でき、表現に制約が少ないという点が最も特徴的と言えるでしょう。また、システム開発用という背景から移植性にも優れ、構造化プログラミングがしやすいです。演算子、データ構造、制御構造を豊富に備えており、高級言語でありながら低水準言語に近いビット操作が行える点も大きな特徴となっています。
ハッキングプログラムやExploitの殆どはC言語で記述されており、多くのハッカーが習得しておくべき言語となっています。しかし、クラッキングをするのが目的であればプログラミング言語は必要ありません。と言いますのも、ハッカーが記述してくれたハッキングプログラムを使用すればクラッキング自体はできてしまうわけですから。
しかし、ハッカーを目指すのであればプログラミング言語を習得しておかなければ、コンピュータの内部まで理解するのは不可能でしょう。どのようにプログラムが作られ、実行されているかを知るのに最も効果的なのはプログラミングを理解することです。
C言語はコンパイル型のプログラミング言語です。コンパイル(Compile)とは翻訳のようなもので、人間基準に書かれたものを機械基準で書かれたものへ変換することです。これを実現するプログラムをコンパイラと呼びます。
機械は0,1の組み合わされた「機械語」と呼ばれる言語しか分かりません。しかし、0と1の羅列だけの言語は人が読みにくいので、一度人が分かりやすい言語で書いてから機械語に翻訳するという方式が一般的です。つまり、この翻訳を行ってくれるのがコンパイラというプログラムです。
また、コンパイル型と対を成すインタープリタ型と呼ばれるプログラミング形式もあります。これは、コンパイル型があらかじめ人が読みやすい形式でかかれたもの(ソースコード)を翻訳しておいてからプログラムを実行するのに対して、インタープリタ型は実行されたときに一行づつソースを読み込んで翻訳し、実行しています。当然読み出しや翻訳などの時間分だけインタープリタのほうが実行速度が遅くなります。遅いにもかかわらず、インタープリタは優れた点があります。それはプログラミングとテストが同時に行えるので、簡単にテストが実行できる点です。これによりデバッグ(バグ除去作業)が容易になります。
C言語のプログラミングの流れは以下のようになっています。
+------------+ |ソースコード| +-----+------+ +---[字句解析] | | ↓ | ←コンパイル----------+---[構文解析] | | ↓ +-----+------------+ +---[意味解析] |オブジェクトコード| | ↓ +-----+------------+ +---[最適化] | | ←リンク------[他のオブジェクトコード等の結合] | +-----+----------+ |ロードモジュール| +----------------+
ソースコードはname.cのように最後に「.c」をつけることでC言語のソースコードであると認識されます。コンパイルにも4つのステップがあり、それぞれの役割は注釈の通りです。コンパイルすることでソースコードを機械語に変換したオブジェクトコードを生成できますが、このオブジェクトコードはただ単に機械語に翻訳しただけのため、まだ実行できません。 実行できるようにするには、リンケージエディタというプログラムを使ってリンクすることで実行できるプログラムであるロードモジュールが生成できます。リンクはOSの提供するライブラリや他のオブジェクトコードを合成したりするステップです。
それではプログラムを作ってみましょう。以下のプログラムは始めてのCプログラムの定番です。テキストエディタを開いて以下のコードを打ち込みましょう。改行やスペースは適当にしてもらって結構です。ただし改行は単語の途中等ではしないようにしてください。
/*****************/
/* hello.c */
/*****************/
#include <stdio.h>
int main(){
printf ("Hello hackers!\n");
return 0;
}
/* Comment */ は、「/*」と「*/」で囲まれた部分をコメントとします。つまり、注釈として人が読むための部分で、コンピュータには見えない部分です。同じように// Comment のように「//」より右から改行までをコメントとしますが、こちらはC++で定義されているコメントですからC言語環境ではエラーになることもありますので、極力控えるようにしましょう。
さて、上記の文字列がプログラムのソースです。テキストエディタに打ち込めたら保存しますが、そのとき拡張子を.cにしてください。名前は適当で良いですが、今回は"hello.c"としておきましょう。
ソースコードを書くときの注意点ですが、ソースの本文中には「"」で囲まれていない部分に全角を使わないようにしてください。特に全角スペースは見つけるのが大変ですのでご注意ください。
保存ができたらhello.cをコンパイルしましょう。Linux, UNIX環境ではgccかccというコンパイラが付属していますので、それを使います。ちなみに、このコンパイラはリンケージエディタも兼ねています。Windows環境では他のテキストで紹介するBorland C++ Compilerを利用してください。gccを使う場合は次のようにします。
$ gcc -o hello.exe hello.c
-oオプションはロードモジュールに自由に名前をつけることができるオプションです。コンパイル時に-oオプションを省いた場合、ロードモジュールの名前はa.exeになります。これでhello.exeというロードモジュールができますので、次のようにして実行します。
$ ./hello.exe Hello hackers!
このように表示されていれば成功です。
それでは解説を行っていきますが、プログラムを解読するにあたって必要となるC言語の仕様を記述します。
まず、スペースや改行は自由に行えます。C言語ではコンパイルに先駆けてスペースと改行を削除します。では文の終わりはどのように判断しているのでしょうか。
文の終わりには「;(セミコロン)」を配置するときめられています。セミコロンがあれば文の終わりに来たと判断できるわけです。つまりhello.cは以下のように書き換えても同じです。
#include <stdio.h>
int main ()
{
printf
("Hello hackers!\n") ;
return 0;
}
このようにプログラマが見やすいと思うように自由に記述できるのです。
#include <stdio.h>
この行は"stdio.h"というファイルをここに埋め込むという指示を表しています。#の付いた行はコンパイルに先駆けて実行されます。また、stdio.hは"standerd I/O"の略で、printfなどの標準入出力を使う場合に埋め込んでおかなければならないファイルです。とりあえず今のところはプログラミングをするときに付けておかないといけない、おまじないみたいなものだと思ってもらえれば良いです。ちなみに#の行は一行に一つの文しか書けません。
int main(){
ここにプログラムを書く
return 0;
}
main()からプログラムが始まります。ここではその前についてるintは無視してください。そしてプログラムが終わるとき0を返して終了する決まりになっています。0以外の数字が返された場合は、エラーが発生した場合です。今のところはまだ関数というものの説明が終わってませんので、プログラミングをするときは上記のように書くと覚えてもらって結構です。関数の説明が済めば大体分かってくると思います。
printf("Hello hackers!\n");
printfは文字をディスプレイ上に表示(出力)します。「"」で囲まれた部分を出力します。ここには全角文字も使ってOKです。\nは改行を表すエスケープシーケンスです。詳しくは他のテキストで説明します。詳しいprintfの使い方も後述することにします。