1 次元配列

  ある変数がスカラー(単純変数)ではなく,配列変数であることを定義するためには,例えば,以下のように記述します.int の箇所には,double などの基本型のほか,クラス名なども記述できます.
int x[10];		
  このように定義することにより,変数 x は 10 個の要素を持った配列変数( 10 次元のベクトル)とみなされ,この場合は,10 個の倍精度実数を記憶するために 80( 8×10 )バイトの連続した領域が確保されます.なお,基本的に,要素の数は定数でなければなりません.ただし,const 宣言された変数 n を使用して,
const int n = 10;   // n の値は変更できない
double x[n];		
のように,宣言することは可能です.例えば,下の例のように,入力するデータの数に応じて配列を宣言したいことがしばしば起こりますが,不可能な場合がありますので注意してください( C/C++ のバージョンによっては可能).以下のような処理を行いたい場合は,new 演算子を使用する必要があります.
int n;
printf("データの数を入力してください ");
scanf("%d", &n);
double x[n];   // 避けた方が良い		
  配列の各要素を参照するためには,ベクトルの場合と同様に,x[i] のように記述すればよいことになります.ただし,添え字 i は,ベクトルとは異なり,上のように定義した場合,0 から 9 まで変化します.従って,
x[5] = 3.0;
y    = x[3];		
と書くと,配列 x の 6 番目の要素( 5 番目でないことに注意)に値 3.0 が代入され,4 番目の要素に入っている値が変数 y に代入されます.このように,配列の参照や代入は,添え字を利用して各要素ごとに行えますので,たとえば,配列 x の 2 から 15 番目の要素を配列 y の先頭部分にコピー(代入)したい場合は,以下に示すように,繰り返し文を使用して簡単に実行できます.14 個の単純変数を他の 14 個の単純変数に代入する場合と比較してみて下さい.
for (i1 = 1; i1 <= 14; i1++)   // i1 の値に注意
	y[i1-1] = x[i1];		
  3章で述べましたように,
char c = 'x';		
と宣言することにより,変数 c には 1 文字だけ記憶できます.この例では,その変数を「x」という文字で初期化しています(「'」が使われていることに注意).複数の文字,つまり,文字列を記憶するためには,複数の文字型変数を必要とします.従って,配列が重要な役割を果たします.

  例えば,9 個の文字( 10 個ではない)からなる文字列を,配列を使用して記憶するためには,
char z[10];		
という宣言が必要になります.なぜなら,配列を利用して文字列を扱う場合,文字列の最後には文字列の終わりであることを示す「 \0 」( NULL 文字)という文字を入れておく必要があるからです( NULL 文字を使用しないで記憶することも可能ですが,文字列の扱いが面倒になります).そのため,(文字列の長さ+1)以上の大きさの配列を定義しておく必要があります.

  char 型変数に対する入出力についても述べておきます.以下の例では,変数 z に対して,「 char z[10]; 」の宣言がされているものとします.なお,NULL 文字を使用せずに文字列を扱いたい場合は,%s を使用した入出力方法を利用できませんので,1 文字ずつ入力することになります.
scanf("%c", &z[2]);     // z の 3 番目の要素に 1 文字入力する
scanf("%s", z);         // 9 文字以下の文字列を入力する
                        // (文字列の最後に \0 が付加される)
printf("%c\n", z[2]);   // z の 3 番目の要素を出力する
printf("%s\n", z);      // 文字列を出力する		
  配列に対する初期化も,単純変数と同様,可能です.しかし,配列表現の場合とポインタ表現の場合とでは,微妙な違いがありますので注意して下さい.例えば,以下のような宣言により初期化を行ったとします.
int x1[4] = {1, 2};   // int x1[4] {1, 2}; も OK
int x2[] = {1, 2};   // int x2[] {1, 2}; も OK
int *x3 = {1, 2};     // 誤り
char c1[15] = {"test data"};   // {} は無くても良い
char c2[] = {"test data"};   // {} は無くても良い
char *c3 = {"test data"};   // {} は無くても良い(避けた方が良い)
int x1[4] = {0};    // すべての要素が 0 で初期設定される		
  1 行目の場合は,配列変数 x1 に対し,4 つの値が入る領域がとられ,その最初の 2 つが 1 と 2 に初期設定されます.2 行目の宣言に対しては,同様に配列変数 x2 の 2 つのデータに対する初期設定が行われますが,2 つのデータが入る領域しか確保されません.このように,初期設定する場合は,「[]」内の数字を書かなくても,構いません.しかし,3 行目の表現は許されません(ポインタ変数 x3 そのものを初期化するものとみなされる).

  文字型の場合も,基本的には,上で述べた int 型に対する場合と同じです(ただし,{} は無くても良い).4 行目では,15 字入る領域が確保され,最初の 10 文字に "test data\0" が保存されます.5 行目では,同じように 10 文字が記憶されますが,領域として 10 文字分しか確保されません.また,文字列に対しては,6 行目の表現も可能ですが,警告メッセージが出力されます.このような表現は避けた方が良いと思います.

  すべての要素を 0 で初期設定したい場合だけは,最後の行のような表現が許されます.初期設定したい値が 0 でないときは,1 行目のように,最初の要素だけが初期設定されます.

  また,new 演算子を使用して,
double *x = new double [10];
double *x = new double [10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};   // 初期設定も OK		
のような形で配列を定義することも可能です.この文によって,10 個の倍精度実数を記憶するために 80( 8×10 )バイトの領域が確保され,その先頭アドレスが変数 x に代入されます.通常の配列とは異なり,「 10 」の箇所に変数を使用することも可能ですので,ダイナミックに領域を確保できます.その参照方法等に関しては,上で述べた方法とほとんど同じです.しかし,確保可能な領域の大きさは異なってくる可能性があります(コンパイラやコンピュータによって異なる可能性がある).例えば,以下に示すプログラムの断片において,配列を使用する場合は正しく動作せず,new 演算子を使用する場合は正しく動作します.これは,new 演算子を使用した場合,その領域が,プログラム実行時に任意に確保や解放を繰り返すことができるメモリ領域(ヒープ領域,ヒープメモリ,heap memory )に確保されるからです.
//	int x[5000000];   // 実行できない
	int *x = new int [5000000];   // 実行可
	x[4999999] = 100;
	printf("%d\n", x[4999999]);