質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1219閲覧

C言語 2次元配列のポインタについt

north_redwings

総合スコア32

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

0クリップ

投稿2017/12/30 02:20

編集2017/12/30 02:41

C

1コード 2//多次元配列でのポインタ利用 3#include <stdio.h> 4 5#define row 3 //行 6#define col 2 //列 7// 56 60 8//54 65 9//12 98 10 int main(int argc, char const *argv[]) { 11//点数入力 12int score[row][col] = {{56, 60}, {54, 65}, {12, 98}}; 13//ポインタ利用で要素表示 14//行ごとに表示 15printf("\n"); 16for (int i = 0; i < row; i++ ){ 17 printf("\n (score + %d)= %p\t\n\n",i, (score + i) ); 18 19//列ごとに表示 20 for (int j = 0; j < col; j ++){ 21 printf("(*(score + %d) + %d) = %p\t\n",i, j, (*(score + i) + j) ); 22 printf("*(*(score + %d) + %d) = %d\t\n",i, j, *(*(score + i) + j) ); 23 } 24 printf("\n"); 25} 26printf("\n"); 27 return 0; 28}

これを実行するとErrorなく次のようになりました。

C

1コード 2 (score + 0)= 0x7ffee0038a30 3 4(*(score + 0) + 0) = 0x7ffee0038a30 5*(*(score + 0) + 0) = 56 6(*(score + 0) + 1) = 0x7ffee0038a34 7*(*(score + 0) + 1) = 60 8 9 10 (score + 1)= 0x7ffee0038a38 11 12(*(score + 1) + 0) = 0x7ffee0038a38 13*(*(score + 1) + 0) = 54 14(*(score + 1) + 1) = 0x7ffee0038a3c 15*(*(score + 1) + 1) = 65 16 17 18 (score + 2)= 0x7ffee0038a40 19 20(*(score + 2) + 0) = 0x7ffee0038a40 21*(*(score + 2) + 0) = 12 22(*(score + 2) + 1) = 0x7ffee0038a44 23*(*(score + 2) + 1) = 98 24

これを見るに、score+0は0行目の一番最初の要素、すなわち0行0列のscore[0][0]のAdressを格納するポインタ変数のように思われます。
score+1についても同様でscore[1][0]のAdressを格納しているポインタ変数のように思われます。
そこで

C

1コード 2 printf("\n *(score + %d)= %d\t\n\n",i, *(score + i) );

を付け加えたところ、

C

1コード 2multi_array.c:17:42: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat] 3 printf("\n *(score + %d)= %d\t\n\n",i, *(score + i) ); 4 ~~ ^~~~~~~~~~~~ 51 warning generated.

のようにErrorが出ました。
そもそも、(score+0)は何を示しているのでしょうか。score+0がscore[0][0]のAdressと一致したのでを先頭につければその要素を示していると考えたのですが...。

まだポインタ変数について理解が浅いので質問がよろしくないかもしれませんがご回答お待ちしています。

rubato6809👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A.Ichi

2017/12/30 02:37

追加された行とエラー(ワーニング)の内容が異なっている様にみれますが。
north_redwings

2017/12/30 02:40

今変更しました、すいません。
guest

回答2

0

ベストアンサー

まず、Warning と Error は違いますよ。ウォーニングは警告ですから期待通りに動作しない可能性はありますが、コンパイルは通り、実行オブジェクトも出来ています。動かしてみることはできます…と、ここまでは簡単です(笑)。

私の手元で、こんなコードをコンパイルしてみました(GCC 5.4.0, x86 64bit)。

C

1 int score[3][2]; 2 3 for (int i = 0; i < 3; i++) { 4 printf(" (score + %d) = %p\n", i, (score + i)); // (A) 5 printf(" *(score + %d) = %d\n", i, *(score + i)); // (B) Warning 6 printf(" *(score + %d) = %p\n", i, *(score + i)); // (C)

実行した結果は、こうです。

(score + 0) = 0x7ffc26f30ff0 *(score + 0) = 653463536 *(score + 0) = 0x7ffc26f30ff0  // 途中省略 (score + 1) = 0x7ffc26f30ff8 *(score + 1) = 653463544 *(score + 1) = 0x7ffc26f30ff8  // 途中省略 (score + 2) = 0x7ffc26f31000 *(score + 2) = 653463552 *(score + 2) = 0x7ffc26f31000

(A)の行と(C)の行の結果は全く同じです(ちなみに (B)の行で表示されている10進数値は、アドレスとして表示されている値の下位32bitを10進数で表示したもの)。

ソースコード上で(A)と(C)の違いは、「(score + i)」と「(score + i)」、即ち「」の有無だけ。「*」があっても無くても結果が同じという、一見訳分からない現象に見えます。
でも、score は二次元配列である事が重要。以下、私の解釈を書きます。

*(score+0)は何を示しているのでしょうか

(score + i) は score[i][0] のアドレスです。でも文法上 (score + i) は、まだ score[i][0] をポイントしていない、score[i][0] と score[i][1] をまとめたモノをポイントしている、そのようにコンパイラは扱っている、即ち「」をつけて「(score + i)」とアクセスし、ポインタを使って取りだした中身は要素数2の配列なのです。そう解釈すれば事情が見えてきます。

さて、Cコンパイラが配列を値として扱う場合、その値は何か?それは配列の先頭アドレスです。そう考えれば、*(score + 0) == (score + 0) で良いのではないでしょうか。

以上から、次のようなアクセスも可能だとわかりますが

C

1 printf("%d\n", *(score + i)[0]); 2 printf("%d\n", *(score + i)[1]);

ここは素直にこうすれば、ややこしいことに悩まずに済むと思うのですが、いかがですか。

C

1 printf("%d\n", score[i][0]); 2 printf("%d\n", score[i][1]);

投稿2017/12/30 08:08

編集2017/12/30 08:34
rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

north_redwings

2017/12/30 08:38

ありがとうございます。 自分でも考えた結果なんとなくそう解釈するのが妥当かなと考えていたところに同様なご回答をいただいたので安心しました。 そうですね、(笑)。 ただ、今回は行列の動的メモリ確保のコードを理解するために一段階下げたコードで理解しようとしたものですからポインタを利用しました(笑)。 解決しました、本当にありがとうございました。
guest

0

そもそも、そもそも、*(score+0)は何を示しているのでしょうか。は何を示しているのでしょうか。

scoreのアドレスの0番目のアドレスを示しています。*(score+1)はscre[]の二番目のアドレスを指しています。
*(score+2)は3番目なので &score[2][0]という事になります。
ですので下記の様にも書けます。

c

1  int *scorep; 2 scorep = (int *)score; 3 for (i = 0; i < row*col; i++ ){ 4 printf("*(scorep + %d) = %d\t\n",i, *(scorep + i)); 5 }

そのアドレスの前に’*’を付けると値となります。

printf("\n *(score + %d)= %d\t\n\n",i, *(score + i) );

ワーニングはドレスを%dで表示させようとされたからです。

こちらの方が良いですね

for (i = 0; i < row*col; i++ ){ printf("*((int *)score + %d)) = %d\t\n",i, *((int *)score + i)); }

投稿2017/12/30 02:58

編集2017/12/30 10:32
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

north_redwings

2017/12/30 07:56

score+iは何なのでしょうか? score+1がscore[1][0]のアドレスと一致しているので混乱してきました。
A.Ichi

2017/12/30 09:22

score+iは、scoreのi番目です。ですのでscore+1は、score[0][1]と同じです。
rubato6809

2017/12/30 09:26

> *(score+2)は3番目なので &score[1][0] は間違いでしょう。動かしてみましたか?>A.Ichiさん
A.Ichi

2017/12/30 09:40

ご指摘ありがとうございます。間違っておりました。&score[]のアドレスですね。score+1は、score[1]と同じですね。訂正しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問