水流さんへC言語講座 ー HelloWorld編

@kaorin_linux さんによるC言語講座。
4
かおりん@ @kaorin_linux

予定外の時間に目が覚めてしまった。特にやることも予定してない。微妙にこまった。♡

2010-12-25 03:18:39
かおりん@ @kaorin_linux

水流さん相手に勝手にC言語講座。♡

2010-12-25 03:19:21
かおりん@ @kaorin_linux

おもむろにねとびんを起動してみたり。LinuxでC動かすのって初めてか?♡

2010-12-25 03:20:28
かおりん@ @kaorin_linux

ありがちなサンプル。 #include <stdio.h> int main(int argc, char** argv) { printf("Hello world\n"); return 0; }♡

2010-12-25 03:23:38
かおりん@ @kaorin_linux

C言語は、言語仕様に入出力とか盛り込まれてないので、基本的にライブラリを利用することになります。そのため、一行目のinclude <stdio.h>で標準的な入出力のライブラリを使用しますよ、と宣言します。♡

2010-12-25 03:25:53
かおりん@ @kaorin_linux

2行目は、関数の宣言となります。C言語では、プログラムの実行はmain関数から始まるお約束があります。これは、アセンブラで言うところの実行開始アドレス指定と同じもので、変えることは出来ません。なので、mainから始まる関数が必ず必要です。♡

2010-12-25 03:28:05
かおりん@ @kaorin_linux

関数宣言の最初のintは、この関数の返値です。この関数は整数を値として返す、という意味ですね。次のmainが関数の名前になります。♡

2010-12-25 03:31:27
かおりん@ @kaorin_linux

関数名の後に()で括られているのが、この関数を呼び出されるときに与えられる引数です。♡

2010-12-25 03:32:08
かおりん@ @kaorin_linux

引数とは何か、というと、関数というものの性格を考えてもらえれば明らかな通り、その関数の入力値のことです。main関数は、argcとargvの二つの引数を入力として受け取り、int型の値を返す、というのが2行目の宣言の意味です。♡

2010-12-25 03:34:51
かおりん@ @kaorin_linux

main関数の場合、二つの引数を取ります。最初のint argcは、int型の引数で、コマンドラインの数となります。これは自分自身のコマンド名も含まれるので、必ず1となりますね。♡

2010-12-25 04:37:03
かおりん@ @kaorin_linux

二ツ目のchar** argvは、実際にコマンドライン引数に渡された文字列の配列です。C言語の場合には文字列型というものがないので、文字列は、char型の配列、またはポインタで表されます。♡

2010-12-25 04:38:08
かおりん@ @kaorin_linux

つまり、char** というのは、char[][]と同様というか、文字型の2次元配列としても扱えるということになります。例えば、char[0]としてargvにアクセスすると、実行されたコマンドが取得出来ます。♡

2010-12-25 04:39:23
かおりん@ @kaorin_linux

CLIアプリなどの場合には、このargvから、コマンドラインのオプションやファイル名などを受け取って処理するわけです。♡

2010-12-25 04:40:04
かおりん@ @kaorin_linux

ちなみに、argvを引数として渡すとオプションに分解してくれる便利な関数があったはずですが、忘れました。(笑)♡

2010-12-25 04:40:48
かおりん@ @kaorin_linux

ここでひとつ、C言語での文字列について触れておきましょう。♡

2010-12-25 04:41:15
かおりん@ @kaorin_linux

C言語には、前述の通り、文字列型というものはありません。文字列は文字の集まり、連続したメモリの領域として言語には認識されます。その場合、では、終わりはどこなのか、という印が必要になります。C言語の場合には\0が終端文字として扱われます。♡

2010-12-25 04:42:41
かおりん@ @kaorin_linux

例えば"ABC"という3文字の文字列があった場合、実際にメモリ領域として確保されるのは、終端文字\0を含めた「4文字分」ということになります。この点は覚えておかないと、メモリ確保の場合や、メモリコピー時の終端文字列抜けによるセグフォに繋がり易いので、ひとつのポイントでしょうか。♡

2010-12-25 04:44:34
かおりん@ @kaorin_linux

C言語入門書が「ワリと躓きやすい」メモリ破壊の要因の一つですね。♡

2010-12-25 04:45:30
かおりん@ @kaorin_linux

で、argvの話に戻りますが、コマンドラインの引数というのは、複数指定出来るため、配列として受け取る必要があります。また、文字列も配列です。そのため、2次元の文字型の配列、つまり、ポインタのポインタとして表現されるため、char **argvという書き方になるわけです。♡

2010-12-25 04:47:16
かおりん@ @kaorin_linux

C言語では、ある決まった大きさのメモリ領域を「配列」として扱います。もちろん、配列の「型」によって実際の大きさは異なるわけですが。♡

2010-12-25 04:48:17
かおりん@ @kaorin_linux

配列は、その先頭のメモリアドレスを持つ、単なる領域に過ぎないわけです。♡

2010-12-25 04:48:42
かおりん@ @kaorin_linux

一方で、ポインタとは何か、というと、「メモリアドレスそのもの」なわけです。ポインタに配列のアドレスを代入してしまえば、そのまま配列アクセスにも使えます。また、配列の先頭アドレスは固定されていて動かせませんが、ポインタの場合には、「演算」を行うことが出来ます。♡

2010-12-25 04:50:52
かおりん@ @kaorin_linux

ポインタが格納しているのは、メモリアドレス、単なる住所なので、足したり引いたりが可能ということです。なので、配列のアドレスは、Aさんの家を指していて、一度ポインタに、Aさんの家のアドレスを代入した後に、ポインタに1を足すと、次の家、Bさんの家のアドレスにする、なんてことが出来ます

2010-12-25 04:52:15