teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

[3] を [2] に修正

2020/03/11 09:59

投稿

rubato6809
rubato6809

スコア1382

answer CHANGED
@@ -55,7 +55,7 @@
55
55
  ---
56
56
 
57
57
  追記です。
58
- 前者の func(str[3][15]); ではなく、後者の func(str); という呼出したというので重篤ではなかったとホッとしています。
58
+ 前者の func(str[3][15]); ではなく、後者の func(str); という呼出しだったというので重篤ではなかったとホッとしています。
59
59
 
60
60
  > ポインタ配列でも二次元配列でもデータ構造が違うだけで要素へのアクセスの仕方などは同じ(e.g. str[1][2])なのにどうしてエラーがでるのでしょうか。
61
61
 
@@ -64,7 +64,7 @@
64
64
  void func(char *str[]) と引数を受け取った関数が str[1][2] をアクセスする時、
65
65
  1. str ポインタが指す所にはポインタ配列があるはずだ。
66
66
  2. そのポインタ配列の2番目のポインタを読む。私の図(D)で言えば「int型データのアドレス」の[1] でインデックスされたポインタを読む、ということ。それが str[1] です。
67
- 3. さらに、そのポインタが指す配列の[2]ですから3番目の要素が str[1][2] です。これは (str[1])[3] という意味です。
67
+ 3. さらに、そのポインタが指す配列の[2]ですから3番目の要素が str[1][2] です。これは (str[1])[2] という意味です。
68
68
 
69
69
  つまり、ポインタ配列を経由して目的の要素をアクセスするのが char *str[] における str[1][2] です。
70
70
  ところが char str[3][15]; という配列にはポインタ配列はありません。あるのは実データです。

2

字句修正

2020/03/11 09:59

投稿

rubato6809
rubato6809

スコア1382

answer CHANGED
@@ -55,11 +55,11 @@
55
55
  ---
56
56
 
57
57
  追記です。
58
- 前者の func(str[3][15]); ではなく、後者の func(str); という呼出したとうのであれば重篤ではなかったとホッとしています。
58
+ 前者の func(str[3][15]); ではなく、後者の func(str); という呼出したとうので重篤ではなかったとホッとしています。
59
59
 
60
60
  > ポインタ配列でも二次元配列でもデータ構造が違うだけで要素へのアクセスの仕方などは同じ(e.g. str[1][2])なのにどうしてエラーがでるのでしょうか。
61
61
 
62
- 誤解してます。同じなのは ``` str[1][2] ``` というコードの字面であって、データ構造が違うため**要素へのアクセスの仕方は違う**のです。
62
+ 誤解してます。同じなのは ``` str[1][2] ``` というコードの字面であって、データ構造が違うのだから**要素へのアクセスの仕方は違う**のです。
63
63
 
64
64
  void func(char *str[]) と引数を受け取った関数が str[1][2] をアクセスする時、
65
65
  1. str ポインタが指す所にはポインタ配列があるはずだ。

1

追記

2020/03/11 09:52

投稿

rubato6809
rubato6809

スコア1382

answer CHANGED
@@ -50,4 +50,32 @@
50
50
  ```
51
51
 
52
52
  これは **str 配列の先頭アドレス**をfunc() に渡したという意味になります。
53
- さらには、この2つ以外の可能性も考えられます。そして、どう書いたのか、それによっては、もっと重篤な誤解をしている可能性があります。さあて、どうなんでしょうか?
53
+ さらには、この2つ以外の可能性も考えられます。そして、どう書いたのか、それによっては、もっと重篤な誤解をしている可能性があります。さあて、どうなんでしょうか?
54
+
55
+ ---
56
+
57
+ 追記です。
58
+ 前者の func(str[3][15]); ではなく、後者の func(str); という呼出したとうのであれば重篤ではなかったとホッとしています。
59
+
60
+ > ポインタ配列でも二次元配列でもデータ構造が違うだけで要素へのアクセスの仕方などは同じ(e.g. str[1][2])なのにどうしてエラーがでるのでしょうか。
61
+
62
+ 誤解してます。同じなのは ``` str[1][2] ``` というコードの字面であって、データ構造が違うため**要素へのアクセスの仕方は違う**のです。
63
+
64
+ void func(char *str[]) と引数を受け取った関数が str[1][2] をアクセスする時、
65
+ 1. str ポインタが指す所にはポインタ配列があるはずだ。
66
+ 2. そのポインタ配列の2番目のポインタを読む。私の図(D)で言えば「int型データのアドレス」の[1] でインデックスされたポインタを読む、ということ。それが str[1] です。
67
+ 3. さらに、そのポインタが指す配列の[2]ですから3番目の要素が str[1][2] です。これは (str[1])[3] という意味です。
68
+
69
+ つまり、ポインタ配列を経由して目的の要素をアクセスするのが char *str[] における str[1][2] です。
70
+ ところが char str[3][15]; という配列にはポインタ配列はありません。あるのは実データです。
71
+
72
+ 関数を func(str); と呼び出す時、関数 func に渡されるのは配列 str の先頭アドレスです。私の図(B)に書いた「先頭アドレス」が渡されるという事。繰り返しますが、そのメモリにあるのはポインタ配列ではありません。よって関数は配列の中の要素をアクセスできません(無理にアクセスすれば高い確率で不正なメモリアクセスを起こし異常終了する。場合によっては実際に起こりうる)。
73
+
74
+ 一方、配列の先頭アドレスを受け取った場合、str[1][2] をアクセスするのは、**先頭アドレス+(15 * 1 + 2)と計算するアドレスのメモリ**をアクセスするということです。この計算にポインタ配列は不要です。
75
+
76
+ 配列 char str[3][15]; を関数に渡したいなら、関数側は
77
+ ```C
78
+ void func(char str[][15])
79
+ {
80
+ ```
81
+ と受け取ってください。これで良いことは太字で強調したアドレスの計算式から読み取っていただきたい。