本物のC

C の基本:変数


宣言と利用

変数は基本的に

型 識別子;

と書く事で宣言・定義されます。(しかしこれは習慣的に「変数宣言」と呼ばれます。)

この変数を利用可能な範囲はスコープ(scope)と呼ばれますが、これは変数を宣言した場所などによって異なります。またそれに伴い、仮想メモリ上の変数の配置も変わってきます。

宣言をソースコードに直接、何らかの関数の中ではない部分へ書いた場合、その変数はグローバル変数(global variable、大域変数)となります。グローバル変数はデータセグメントの中の領域として確保され、同じファイルのコードからはいつでもアクセスできます。

一方で関数の中に書いた場合、その変数はローカル変数(local variable、局所変数)となります。ローカル変数は関数を呼び出した時にスタックの中に確保され、その関数の中のコードでしかアクセスできません。(ただし先頭にstaticを付けて静的変数として宣言した場合、グローバル変数と同様データセグメント中に確保されます。)

変数の値(バイト列)は実行中に色々と変える事ができ、例えばaという変数の値を 0 にする場合

a = 0;

と書きます。こうして値を設定する操作を代入する(assign)と言います。

バイトオーダー

aへ次の値を代入したとしましょう。

a = 0x01020304;

この値はバイト列としては 0x01 0x02 0x03 0x04 なのですが、Intel の CPU ではこれが

アドレス
: :
0x0028FF2A ?
0x0028FF2B ?
0x0028FF2C 0x04 a
0x0028FF2D 0x03
0x0028FF2E 0x02
0x0028FF2F 0x01
0x0028FF30 ?
: :

と下位バイトから逆順に配置されます。

バイト列の並べ方はバイトオーダー(byte order)と呼ばれ、上の様に逆順になるのはリトルエンディアン(little endian)、反対に上位バイトから順に配置されるのはビッグエンディアン(big endian)と言います。

処理系のバイトオーダーは次のコードで確認する事ができます。

#include <stdio.h>
int main(void)
{
int a = 0x01020304;
printf("%02x %02x %02x %02x\n",
*((char*) &a),
*((char*) &a + 1),
*((char*) &a + 2),
*((char*) &a + 3));
return 0;
}

リトルエンディアン/ビッグエンディアンとは妙な用語ですが、これは『ガリヴァー旅行記』の「卵を小さい方の端から割る派」と「卵を大きい方の端から割る派」から来ている様です。(参考:「エンディアンの由来」)