Code Fix

中級

多次元配列で行と列の添字を取り違えて違う値を読む

arr[row][col]とarr[col][row]は多くの場合どちらもコンパイルは通り実行もできますが、正方でない配列では違う位置の値を読んでしまいます。

なぜエラーが出ないのか

出力: 7
(エラーなし)
Cは何も報告しません。コンパイルも実行も正常に完了するためです
出力: 7
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  #include <stdio.h>
 2  
 3  int main(void) {
 4      int grid[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
 5      int row = 0, col = 2;
 6      printf("%d\n", grid[col][row]);
                                ^
 7      return 0;
 8  }
出力: 7期待: 3

grid[row][col]とgrid[col][row]はどちらも配列の範囲内なのでエラーにはなりませんが、対称でない行列では違う位置の値を読んでしまいます。

直し方: col][rowrow][col にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  #include <stdio.h>
 2  
 3  int main(void) {
 4      int table[3][3] = {{10, 20, 30}, {40, 50, 60}, {70, 80, 90}};
 5      int row = 1, col = 0;
 6      printf("%d\n", table[col][row]);
                                 ^
 7      return 0;
 8  }
出力: 20期待: 40

行と列のどちらを先に書くかは、配列を宣言したときの次元の順序と揃える必要があります。

直し方: col][rowrow][col にします。

この問題を解いてみる →

パターン3

 1  #include <stdio.h>
 2  
 3  int main(void) {
 4      int m[3][3] = {{2, 4, 6}, {8, 10, 12}, {14, 16, 18}};
 5      int row = 2, col = 1;
 6      printf("%d\n", m[col][row]);
                             ^
 7      return 0;
 8  }
出力: 12期待: 16

添字を取り違えても実行時エラーにはならず、たまたま範囲内の別の値が読めてしまうため発見が遅れます。

直し方: col][rowrow][col にします。

この問題を解いてみる →

よくある誤解

配列のサイズが行数と列数で違う場合、添字を逆にすると本来アクセスできないはずの範囲まで読めてしまうことがあり、たまたま動いているように見えるため発見が遅れます。行と列、どちらを先に書くかは配列を宣言したときの次元の順序と揃える必要があります。

まとめ

多次元配列で行と列の添字を取り違えて違う値を読むは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)