掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.29622

3次元配列とポインタ
投稿者---yto(2007/01/28 05:15:39)


すみません、もしかしたらすごい簡単なことかもしれないのですが、あまり時間がないので書き込ませてください。

ポインタ配列から3次元配列に値をうつしたいのですがうまくいきません。
具体的には、

#define X 2*31
#define Y 2*31
#define Z 2*31
double V[Y][X][Z];
long dims[3]={31,31,31};

int main (void) {

double *p;
p = (double *) malloc( dims[0]*dims[1]*dims[2]*sizeof(double) );

/*この間pの指すアドレスを指定します*/

for (i=0; i<Y/2; i++)
for (j=0; j<X/2; j++)
for (k=0; k<Z/2; k++)
V[i][j][k]= p[???];
}

のような感じです。
Vのijkそれぞれ半分までの領域にpが指す値を入れたいのですがiとjが入れ替わってしまうようでうまくいきません。
(i)*dims[0]*dims[0]+((j)*dims[0])+(k)なども試みたんですが違うようです。
どなたかご教授いただけないでしょうか?


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:3次元配列とポインタ 29623 kolona 2007/01/28 07:39:35
<子記事> Re:3次元配列とポインタ 29625 ルナレルナ 2007/01/28 12:52:16


No.29623

Re:3次元配列とポインタ
投稿者---kolona(2007/01/28 07:39:35)


>ポインタ配列から3次元配列に値をうつしたいのですがうまくいきません。

つまり、ポインタで示したメモリにあるデータを3次元配列にきちんと入れ直すということですか?
ポインタ配列は文字通りポインタの配列です。


ポインタの機能を素直に使うのであれば、ポインタに添字に当たる値を加算してやる必要があります。
例えば、配列の保持しているメモリは
X_SIZE =5
Y_SIZE =4
x[X_SIZE][Y_SIZE]の場合、次のようになっています。
*印のあるところが原点で、ポインタpはここを指しています。
もちろん、p==&(x[0][0]) です。
xの値\yの値  0   1   2   3   4
     0       [*] [ ] [ ] [ ] [ ]
     1       [ ] [ ] [ ] [ ] [ ]
     2       [ ] [ ] [ ] [ ] [ ]
     4       [ ] [ ] [ ] [ ] [ ]
     5       [ ] [ ] [ ] [ ] [ ]



次に、yの部分が3の時、ポインタは3つ分進む必要がありますので
p+3==&(r[0][3])  です。
xの値\yの値  0   1   2   3   4
     0       [ ] [ ] [ ] [*] [ ]
     1       [ ] [ ] [ ] [ ] [ ]
     2       [ ] [ ] [ ] [ ] [ ]
     4       [ ] [ ] [ ] [ ] [ ]
     5       [ ] [ ] [ ] [ ] [ ]


で、r[2][3]の時はどうするかっていうと
+の付いた部分をまず足して、それから3を足すことになります。
この+の付いた部分が   (yのサイズ)×(x)   で求められます。
つまり、
p+2*Y_SIZE+3==&(r[2][3])  になります。

xの値\yの値  0   1   2   3   4
     0       [+] [+] [+] [+] [+]
     1       [+] [+] [+] [+] [+]
     2       [ ] [ ] [ ] [*] [ ]
     4       [ ] [ ] [ ] [ ] [ ]
     5       [ ] [ ] [ ] [ ] [ ]

このように、配列にポインタでアクセスするときは、
添字の値より下の次元(配列の添字の右側)のサイズを掛ける必要があります。



今回の場合は、V[i][j][k]=*(p+k+j*Z+i*X*Z);
ですね。

こういうときは、ポインタのアドレスを逐一printf()で表示して観察するとおもしろいですよ。
原理もわかるし。

にしても
double V[Y][X][Z];
はなんでXYZの順にしないんでしょう。ややこしいだけだと思いますが。


この投稿にコメントする

削除パスワード

No.29624

Re:3次元配列とポインタ
投稿者---yto(2007/01/28 11:06:10)


kolonaさん、コメントありがとうございます。

>にしても
>double V[Y][X][Z];
>はなんでXYZの順にしないんでしょう。ややこしいだけだと思いますが。

その通りなんですよね。私が書いたコードではないんですが。。紛らわしいです。


V[i][j][k] = *(p+k+j*Z/2+i*X/2*Z/2);
でいいんでしょうか?
V[i][j][k] = *(p+k+j*Z+i*X*Z);
だとメモリ確保してないためかクラッシュしてしまいます。

これでもうまくいきませんが、printfで確認すると出来ているみたいなのでたぶん私の確認方法が間違っているのだと思います。
なんとか頑張ってみます。ありがとうございました。




この投稿にコメントする

削除パスワード

No.29627

Re:3次元配列とポインタ
投稿者---kolona(2007/01/28 17:18:59)


>V[i][j][k] = *(p+k+j*Z+i*X*Z);
>だとメモリ確保してないためかクラッシュしてしまいます。
>


p = (double *) malloc( dims[0]*dims[1]*dims[2]*sizeof(double) );
を見逃してました。すいません。


この投稿にコメントする

削除パスワード

No.29625

Re:3次元配列とポインタ
投稿者---ルナレルナ(2007/01/28 12:52:16)
http://park6.wakwak.com/~nougaki/mini_program/


/*
    とりあえず「代入のみ」
    動的確保の代わりに単配列を使用
    
    (2 * 31)の大きさや、doubleであったり、
    半分までの領域とういのも省略。
*/

#define X	3	//	塊
#define Y	4	//	行
#define Z	5	//	列

int main (void)
{
    int data_xyz[X][Y][Z];	//	3次元配列
    int data[X * Y * Z];	//	単配列
    int i, j, k;
    
    for (i = 0; i < X * Y * Z; i++)
        data[i] = i;	//	*(data + i) = i;
        
    for (i = 0; i < X; i++)
        for (j = 0; j < Y; j++)
            for (k = 0; k < Z; k++)
                data_xyz[i][j][k] = data[(i * Y * Z) + (j * Z) + k];
                //	data_xyz[i][j][k] =
                //		*(data + (i * Y * Z) + (j * Z) + k);
                
    //	for (i = 0; i < X * Y * Z; i++)
    //		data_xyz[0][0][i] = data[i];
        
    for (i = 0; i < X; i++, putchar('\n'))
        for (j = 0; j < Y; j++, putchar('\n'))
            for (k = 0; k < Z; k++)
                printf(" %2d", data_xyz[i][j][k]);
                
    return 0;
}



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧