C言語で配列の初期化子が要素数より少ない場合にエラーを出したい
C言語でプログラムを組んでいる時に疑問に思い、質問させていただきました。
配列の要素数を明示的に定義している場合において、
初期化子が要素数より多い場合はコンパイルエラーが出るのですが
初期化子が要素数より少ない場合は残りが0埋めされるだけでエラーが出ません。
例えば、ある種のデータ群を配列として持っていて
配列の中身にはそれぞれデータが必ず入っている必要がある
などといった場合に、
配列の要素数の定義だけを増加させると、中身のない領域ができてしまい危険に思いました。
どうにかしてエラーを発生させることはできないのでしょうか?
もしくはコードの書き方等で安全に設計することはできるでしょうか?
コード例
C
1//#define DATA_ARRAY_SIZE 5 → 10 に変更 2#define DATA_ARRAY_SIZE 10 3const int data_array[DATA_ARRAY_SIZE] = { 1,2,3,4,5 };
例えば、こういう場合です。
追記
具体的な状況が伝わりにくかったのでコード例を追記しました。
配列のサイズを取得したいというよりも、
あるサイズ(ここでは列挙体のサイズ)に配列のサイズを紐づけていて
そのサイズが変更された場合に何かしら気付けるような方法があるのかを知りたいです。
C
1typedef enum{ 2 a1 = 0, 3 a2, 4 a3, 5 a_NUM, //この列挙体の要素数 6}eXXX; 7 8const int data_array[a_NUM] = { 1, 2, 3 }; 9 10int main(void) 11{ 12 for (int i = 0; i < a_NUM; i++) 13 { 14 //data_array[i]を使った処理 15 } 16 17 return 0; 18}
上記のコードで、
enumに'a4'が追加された時に、
データ配列的には想定されていない'data_array[3]'にアクセスされることが危険だと感じました。
メモリが余分に確保されているだけで、特に危険は無いように思いますが、const int data_array[] = { 1,2,3,4,5 }; でコンパイルできませんか?
もう一度書きますが、
const int data_array[] = { 1,2,3,4,5 };
でコンパイルできませんか?
ご回答ありがとうございます。
質問が説明不足だと感じ、追記させていただきました。
コンパイルは可能なのですが、余分に確保されたメモリ(適切に初期化されていない)にアクセスしてしまう可能性があることに危険を感じています。
配列のサイズが要素数によってきまるので、そのサイズ外にアクセスしなければいいだけです。
DATA_ARRAY_SIZE とそのサイズが等しいかどうか起動時に一度チェックすればより安全ですが、配列にアクセスするたびにチェックすれば更に安全です。そうしてもさほどパフォーマンスは落ちないでしょう。
特に定義があるわけではないと思いますが、経験上C言語界隈では未定義の動作を引き起こすようなものを特に「危険」と呼ぶのではないでしょうか。
確かに初期化忘れもプログラムの期待しない結果を招くという意味では危険が無いわけではないですが、極論「プログラムの動作をきちんと追っていけば解釈できる」もので、それは単なるバグと呼ぶ気がします。
やりたいこととして理解はできるのですが、「危険」と言われて身構えていたら肩透かしを喰らったような、そんな感じがちょっとするんですよね。
>初期化子が要素数より少ない場合は残りが0埋めされるだけでエラーが出ません。
コンパイラからすると、配列の要素数に満たない部分は残りは0埋めされるとプログラマが分かったうえでやっている状態なわけで。
要素数に満たない部分を0埋めされたくないのなら、要素数を指定しないでおくしかないです。
実行時エラーではなく実行前エラーを出す方法を知りたく今回質問させていただきました。
最終的にはバグであり自己責任というのは重々承知しているのですが、それに気付ける手段として何かあるのであれば知りたいと思った次第です。
皆様ご回答いただき、ありがとうございます。勉強になります。
回答4件
あなたの回答
tips
プレビュー