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

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

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

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

Q&A

解決済

3回答

2125閲覧

C言語 三次元配列の値のコピー

Ann99

総合スコア3

C

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

0グッド

0クリップ

投稿2020/09/09 07:11

前提・実現したいこと

[実現したいこと]
int型の三次元配列(と呼ぶべきかわかりませんが,,)であるdata[3][3][6]の値を
tester[3][3][6]にコピーし,それぞれの値を表示したい.

[前提]
ポインタについて全く理解できていないので,なぜエラーになるか,どのような動きをしているかがわからない.
*と&をつけるべきところがわからない.

発生している問題

表示されたdata[a][b][c]とtester[a][b][c]の値が異なる.

該当のソースコード

C

1#include<stdio.h> 2 3int data[3][3][6];//コピー元の三次元配列 4int **tester[3][3];//コピー先の三次元配列 5 6int main() { 7 for(int i = 0; i < 3; i++){ 8 for(int j = 0; j < 3; j++){ 9 for(int k = 0; k < 6; k++){ 10 data[i][j][k] = i*j + k; 11 } 12 } 13 } 14 int *values;//dataのi行j列の配列をコピーしてtester[i][j]代入するための変数 15 for(int i = 0; i < 3; i++){ 16 for(int j = 0; j < 3; j++){ 17 values = data[i][j]; 18 tester[i][j] = &values; 19 } 20 } 21 22 int a = 1; 23 int b = 2; 24 int c = 5; 25 printf("data : %d\n",data[a][b][c]); 26 printf("tester : %d\n",*tester[a][b][c]); 27 28 return 0; 29}

実行結果

a=1, b=2, c=5にした場合

data : 7 zsh: segmentation fault

a=2, b=2, c=4にした場合

data : 8 tester : 1592313737

補足情報

C言語初心者です.(以前までProcessingを扱っていました.)
ポインタについての理解がないので,用語が不正確であったりコードが不可解であるかもしれません.すみません.
ポインタについての解説でも,どのようにすればうまく実行できるかの説明だけでも構いませんので,
回答よろしくお願いします.

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

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

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

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

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

guest

回答3

0

こんにちは。

質問者さんのコードはコピーではなく、コピー元のアドレスをダブルポインタの二次元配列に設定しようとして失敗しています。

コピーが目的なら素直にtesterをintの3次元配列で宣言すれば良いです。
同じサイズならmemcpyで良いでしょう。

C

1#include<stdio.h> 2 3int data[3][3][6];//コピー元の三次元配列 4int tester[3][3][6];//コピー先の三次元配列 5 6int main() { 7 for(int i = 0; i < 3; i++){ 8 for(int j = 0; j < 3; j++){ 9 for(int k = 0; k < 6; k++){ 10 data[i][j][k] = i*j + k; 11 } 12 } 13 } 14 15 memcpy(tester, data, sizeof(data); 16 17 int a = 1; 18 int b = 2; 19 int c = 5; 20 printf("data : %d\n",data[a][b][c]); 21 printf("tester : %d\n",tester[a][b][c]); 22 23 return 0; 24}

a=2, b=2, c=4にした場合にsegmentation faultしなかったのはたまたまです。
ポインタと配列をもっと勉強しましょう。

投稿2020/09/09 07:23

DreamTheater

総合スコア1095

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

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

Ann99

2020/09/09 08:22

回答ありがとうございます! 勉強不足で申し訳ありません,,, 追加での質問ですが, dataの値を順番を入れ替えながらコピーする,などいう時にはどのようにすれば良いでしょうか? (data[i][j]をtester[j][i]に保存する,など)
maisumakun

2020/09/09 08:36

そういうライブラリを使うか、自力でforループを回して1つずつコピーすることになります。
Ann99

2020/09/09 08:48

分かりました. 回答ありがとうございます.
DreamTheater

2020/09/09 22:37

maisumakunさんフォローありがとうございました。
guest

0

ProcessingというかJavaは、Cとは多次元配列の概念が違います。
Cは単に低次の配列が配列にならんでいるものが多次元の配列ですが、
Javaでは低次の配列をオブジェクトとして持っているのが多次元の配列です。

Processing/Javaに慣れているのなら、関数の引数にしたりするのでなければJavaの構造を再現してやるのがわかりやすいかも知れません。
コメントにJavaで対応するものを書いてみました。

C

1#include <stdio.h> 2int main(void) { 3 int*** data; // int[][][] data; 4 int*** tester; // int[][][] tester; 5 data = (int***)malloc(sizeof(int**) * 3); // data = new int[3][][]; 6 tester = (int***)malloc(sizeof(int**) * 3); // tester = new int[3][][]; 7 for (int i = 0; i < 3; i++) { 8 data[i] = (int**)malloc(sizeof(int*) * 3); // data[i]=new int[3][]; 9 tester[i] = (int**)malloc(sizeof(int*) * 3); // tester[i]=new int[3][]; 10 for (int j = 0; j < 3; j++) { 11 data[i][j] = (int*)malloc(sizeof(int) * 6); // data[i][j]=new int[6]; 12 } 13 } 14 15 for (int i = 0; i < 3; i++) { 16 for (int j = 0; j < 3; j++) { 17 for (int k = 0; k < 6; k++) { 18 data[i][j][k] = i * j + k; 19 } 20 } 21 } 22 int* values; // int[][] values; 23 for (int i = 0; i < 3; i++) { 24 for (int j = 0; j < 3; j++) { 25 values = data[i][j]; 26 tester[i][j] = values; 27 } 28 } 29 30 int a = 1; 31 int b = 2; 32 int c = 5; 33 printf("data : %d\n", data[a][b][c]); 34 printf("tester : %d\n", tester[a][b][c]); 35 36 return 0; 37}

(freeはとりあえず棚上げ)
なお、もとのソースに沿って書いてみましたけど、配列の「コピー」はしていない、というのは大丈夫かしら。
data[a][b][c]=100;
とすると、
tester[a][b][c]も100になりますよ。

投稿2020/09/10 12:31

thkana

総合スコア7703

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

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

Ann99

2020/09/10 16:40

詳しい解説ありがとうございます! Javaでの書き方を併記してくださっているので大変分かりやすいです. 同じものを参照しているから片方の値を変更するともう一方の値も変わる,ということですね? malloc()の使い方もよく分かりました. 回答ありがとうございました!
guest

0

ベストアンサー

実体を指す場所が同じでいいなら

#include<stdio.h> int data[3][3][6];//コピー元の三次元配列 int *tester[3][3];//コピー先の三次元配列 変更 int main() { for(int i = 0; i < 3; i++){ for(int j = 0; j < 3; j++){ for(int k = 0; k < 6; k++){ data[i][j][k] = i*j + k; } } } int *values;//dataのi行j列の配列をコピーしてtester[i][j]代入するための変数 for(int i = 0; i < 3; i++){ for(int j = 0; j < 3; j++){ tester[i][j] = data[i][j];//変更 } } int a = 1; int b = 2; int c = 5; printf("data : %d\n",data[a][b][c]); printf("tester : %d\n",tester[a][b][c]);//変更 return 0; }

でいいんじゃないですか?

投稿2020/09/09 09:21

編集2020/09/09 09:23
PingHermit

総合スコア478

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

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

Ann99

2020/09/10 04:28

回答ありがとうございます. 実態を指す場所は同じで大丈夫なので,これでうまくいきました! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問