Objective-C Primer 番外編 徹底C復習 2.変数

 まずは変数からはじめましょう。変数をできるだけ実態に近い形で説明しようとすれば、
「データを出し入れするための入れ物としてメモリ上に確保された場所につけられた名前」ということになります。この言い方は正確には少し間違っているのかもしれませんが概ねこの通りです。長い説明なので箇条書きにしていくと

1. データを出し入れするための場所がメインメモリー上に確保される
2. その確保されたスペースは名前を付けて使用する
3. データを出し入れできる = 値の変更が可能である

という事になります。
このメモリ上の場所を確保するためにC言語ではまず「確保する」という宣言をしなければなりません。これも正確には「宣言」ではなくて「定義」というのかもしれませんが意味は通じると思います。そしてこの宣言をする時にCの場合はどういうタイプのデータを入れる変数であるのかという事もあらかじめ決めておかなければなりません。まとめると

4. 変数はまず宣言(場所を確保)してから使う
5. 宣言をする時にどういう型のデータを出し入れする変数であるのかも決めておかなければならない

となります。



ここで少し横道にそれますが、C言語以降の後発の言語ではまずこの変数の宣言や定義の仕方がずっと簡単になってきているということは知っておいたほうがいいでしょう。しかしながらObjective-CはそのほとんどがC言語のままなのでここはぐっと堪えてなんとかマスターしなければなりません。
 そしてもう1つ言っておかなければならないことはCに限らずプログラミング言語は何一つ破綻のない神の言葉ではないということです。プログラミング言語は所詮は人間が作ったものなので不条理な所が結構あります。

 では話しを戻しましょう。
さらにCではその変数が使われる範囲(これをスコープといいますが)の冒頭で宣言(メモリ上に確保すること)をしておかなければエラーになります。
具体的に言うと、関数の中で使われる変数は(これをローカル変数と呼びます)、関数のブロック文の始まり( { ←これの事)の直後にその関数の中で使われるすべての変数を確保(宣言)しておかなければエラーになります。なお、この関数の冒頭で確保された変数は特殊な処理がなされないかぎり、その関数が終了する時に自動的に消滅して確保していたメモリ領域も解放されます。
※関数の引数として受け取った変数は宣言しなくてもその関数の冒頭で宣言したのと同じ扱いになります。そしてその引数に付けた名前が変数名として扱われ、関数内から使用することができます。この変数も関数が終了するときに消滅してメモリ領域も解放されます。

 ひとつの関数の中だけで使われるのではなく、すべての関数から使いたい変数が欲しい場合はそのコードファイル、すなわち#import や#include ではじまるソースファイルの冒頭(importやincludeと最初の関数が始まる間のどこかで)宣言しなければなりません。この変数のことをグローバル変数と呼びます。グローバル変数はそのプログラムが終了するまでメモリ上の場所を確保し続けます。逆に言えばプログラムが終了すればそのプログラムで確保していたメモリ領域はすべて解放されます。

註釈
ここで述べているグローバル変数とは1つのファイル、すなわち下記のサンプルコード「scope.c」を例にあげれば、「scope.c」の中のすべての関数から読み書きできる変数となります。通常プログラムはファイル単位でコンパイルされます。これを翻訳単位あるいはモジュールと呼びます。この翻訳単位(モジュール)をリンカというアプリケーションで連結させて最後に実行ファイルができあがります。ただし通常はコンパイルとリンカは続けて行われます。そして普通はこの一連の作業のことをコンパイルと呼びます。
 ここで重要なのはこの翻訳単位を超えて複数のモジュール(複数のソースコードファイル)で利用できるグローバル変数を使用する場合は特殊なコーディングが別途必要になってくるという事を頭の片隅に残しておいてください。

scope.c


01. #include <stdio.h>     // printf関数のためのヘッダファイル読み込み
02.
03. void showGlobal( void );
04. void showLocal( void );
05.
06. int globalVal;        // グローバル変数宣言
07.
08. int main( void ) {
09.   int localVal = 100;   // ローカル変数宣言
10.
11.   globalVal = 1000;
12.   showGlobal( );
13.   printf( "%d\n", localVal );
14.   showLocal();
15.   return 0;
16. }
17.
18. void showGlobal( void ) {
19.   printf( "%d\n", globalVal );
20. }
21.
22. void showLocal( void ) {
23.   int localVal = 10;   // ローカル変数宣言
24.
25.   printf( "%d\n", localVal );
26. }

コード説明
1行目では「printf()関数」のためのヘッダファイルを読み込んでいます。printf関数の使いかたはNSLog()関数の使いかたとほぼ同じです。詳しい使用方法はviva Cocoa ホームページの「Objective-C Primer 第5回 NSLog」をお読み下さい。printfでは文字列の冒頭で自動的に改行されますが、NSLogでは文字列の最後が自動的に改行されます。またprintfではNSStringを扱うことはできません。従って「@」ではじまる「@"あいうえお"」などの文字列は使えません。printf関数とNSLog関数の相違点は以上の2点だけです。
6行目でグローバル変数を宣言しています。ちょうど関数プロトタイプの宣言とmain関数の間で宣言しています。
9行目と22行目ではローカル変数を宣言しています。どちらもブロック文「{」の直後に宣言しています。なおローカル変数はその関数内のみで有効なので関数が違えば同じ名前を付けてもまったく問題ありません。また関数内にグローバル変数と同じ名前のローカル変数が存在する場合はそのローカル変数のほうが優先されてグローバル変数は使えなくなります(このような状況のことを「隠れる」とも言います)。


上記のサンプルコードの打ち込みが終りましたら好みのところに「scope.c」という名前で保存してください。私の場合はデスクトップの「vivacocoa」というフォルダの中に保存しました。次にターミナルを起動して下記のように操作します。
cd Desktop/vivacocoa
デスクトップのvivacocoaフォルダに移動します。違う場所に保存された場合はそこに移動してください。cd は移動を意味します。「../」で1つ上の階層に移動できます。下の階層に移動する場合はそのままファルダ名を指定します。続けて下の階層に移動する場合は上記のように「/」で区切ります。
ls
そのフォルダの中のファイルを一覧表示します。「scope.c」が出来ているか確認してください。
cc scope.c
「scope.c」をコンパイルします。エラーがでれば「scope.c」を修正してください。無事にコンパイルが完了すると同じフォルダに「a.out」という実行ファイルができあがります。
./a.out
実行する際には、「a.out」の前にカレントディレクトリを表す「./」を先頭に付けます。
cc -o scope scope.c
このようにしてコンパイルすると実行ファイル名は「a.out」でなくて「-o」というオプションの後に指定した名前になります。この例の場合は「scope」という名前になります。

この実行結果は次のようになります。
d0122908_1353949.gif

[PR]
by vivacocoa | 2007-04-28 21:58


<< Objective-C Pri... Objective-C Pri... >>