配列は新しく宣言する時に初期化しておく事が大切ですが、
初期化する方法がいくつかありますので、ご紹介します。
用途によって使い分けて下さい。
宣言と同時に初期化する(int型)
int array[3] = {0,0,0};
int array[3] = {10,20,30};
int array[] = {0,0,0};
int array[] = {10,20,30};
int型の場合は上記のように記述する事ができます。
省略した書き方
また、次のようにも記述する事ができます。
int array[5] = {10,20,30}; //結果 [0]=10 [1]=20 [2]=30 [3]=0 [4]=0
int array[5] = {0}; //結果 [0]= 0 [1]= 0 [2]= 0 [3]=0 [4]=0
1行目の場合、最大要素数5に対して
3つだけ数値を指定して初期化した例です。
3つ目までは予想通りですが、
後ろの残り2つが0で初期化されます。
2行目の場合、すべての要素が0で初期化されます。
このような書き方は推奨され無いと思いますが、
問題なくプログラムが動作するのであれば、便利な書き方です。
宣言と同時に初期化する(char型)
char array[3] = { 'a', 'b', 'c' };
char array[] = { 'a', 'b', 'c' };
char array[4] = "abc";
char array[3] = "abc"; // エラー
char array[] = "abc";
char str[13] = "aaa日本語bbb";
char型の場合は上記のような初期化方法があります。
5行目に記述した方法を使うと、
要素数を書く必要がなく、とても便利です。
全角文字は2バイトとして扱われますので、注意が必要です。
また、char型配列を文字列として使うのであれば、
先頭の値だけ\0にしておく。と言うのも初期化の1つの方法です。
char str[10];
str[0] = '\0';
文字列リテラルを使う際の注意
“”で囲んだ文字列を「文字列リテラル」と呼びますが、
文字列リテラルを使って初期化する場合は注意する必要があります。
#include <stdio.h>
int main(void) {
char a[] = "aaa";
char* b = "bbb";
a[0] = 'e'; // 問題ない
printf(a);
b[0] = 'k'; // 書き換え不可
}
このプログラムは、異常終了してしまいます。
それはなぜか理解できますか?
char a[] = “aaa”; と書くと、
内部的には、”aaa”がどこかの領域に確保され、
さらにそのデータが、どこかの領域にコピーされて、
そのコピーされたデータの先頭アドレス値が変数aに設定されます。
ややこしいですが、
簡単に言うと、書き換え可能な配列aを作成しました。
と言う事です。
書き換え可能ですから、
a[0] = ‘e’; と言う処理も問題なく行われます。
次の文を見てみましょう。
char* b = “bbb”
これは、”bbb”と言うデータをどこかの領域に確保し、
その先頭アドレスがbに設定されます。
文字列リテラルで確保されるデータは書き換え不可になってしまうのです。
ですから、そのあとに書き換えようとすると
エラーか例外発生、もしくは異常終了となってしまうのです。
書き方が紛らわしいので、注意が必要です。
要素数が多い場合の初期化方法
例えば必要な要素数が30、100と言う感じだと、
初期化する数値を1つ1つ入力するのは手間ですよね。
そういう場合には、繰り返し制御文を使って初期化します。
int array[100];
for (int i = 0; i < 100; i++) {
array[i] = 0;
}
for文を使って配列を初期化しています。
また、ページ上部の「宣言と同時に初期化する(int型)」
の項でも説明しましたが、
int array[100] = {0}; と言う書き方でも実現できます。
char型やshort型でも実際に試してみましたが、
同じように初期化されました。
しかし、他の型や他のC言語環境では試していませんので、
基本的にはループ処理で値をセットした方が無難だと思います。
char型配列を初期化する memset
今度は、memset関数で初期化する方法をご紹介します。
memset関数の使い方
char array[100];
memset(array, 0, sizeof(array));
memset関数は、簡単に言うと、メモリにデータをセットする関数です。
第1引数 セットする開始地点のアドレス
第2引数 セットしたい値
第3引数 セットしたい領域(バイト数)
上記のように設定します。
第1引数はarrayと記述していますが、
&array[0]と同じ意味になります。
sizeof(array)と書くと配列のサイズを数値で返してくれますので、
便利な記述方法になります。
この例の場合、配列の先頭から配列の最後までの領域が0になります。
結構便利な関数ですが、
memset関数はバイト単位で処理してしまうので、
2バイト、4バイトを扱うデータ型配列などでは
うまく機能してくれません。
0以外の同じ値で初期化したい場合
char array[100];
memset(array, 1, sizeof(array));
memset関数の第2引数に指定すれば実現できます。
この場合も1バイトのデータ型変数限定です。
それ以外のデータ型配列の場合は、
for文などで記述するようにします。
int array[100];
for (int i = 0; i < 100; i++) {
array[i] = 1;
}