C言語で、2次元配列の構造体を関数に渡したい
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
NGNG人に聞くのは良くないとわかってはいますが
なにとぞお願いします。
0002名無しさん@お腹いっぱい。
NGNG参照渡しなら余裕っしょ
struct s{
...
};
func( struct s** xy){
...
}
main(){
struct s xy[X][Y];
func( xy);
}
こんなかんじ。
つーか、2次元配列の構造体って言葉が
どういうデータ構造を指すのかちょっとわかりにくいんで、
はずしてるかもしれんが。
0003名無しさん@お腹いっぱい。
NGNGstruct foo{
int x;
}Foo[10][10];
なら
func(struct foo Foo[10][10]){
...
}
main(){
func(Foo);
}
でええんでないかい?
0004名無しさん@お腹いっぱい。
NGNG0005>1
NGNG出来ないですけど・・・
そういうことですか?
00061
NGNGstruct obj{
int x@`y@`z;
}array[10][10];
とかこんな感じです。
頭のアドレスだけでも関数に渡せればいいんですけど
ドキュンなもんで難しい・・。
2さんの方法は何回かやってみたけどダメでした。
3さんのやりかたで試してみます。
00071
NGNGpassing arg 1 of 'func' from incompatible pointer type
っていうwarningがでます。
根本的な事が間違ってるんでしょうか?
0008名無しさん@お腹いっぱい。
NGNG0009名無しさん@お腹いっぱい。
NGNGstruct foo** Foo かな?
どうでしょ?
00101
NGNG*をつけないで普通に配列を渡すときのようにしたら
できました。
なぜ?
みなさん、ありがとう
0011名無しさん@お腹いっぱい。
NGNG0012Rockewell
NGNGvoid func(struct obj *);
func(&array[0][0]);
00131
NGNGでも正しいサイズを入れないとwarningでるけど、、。
struct foo Foo[][10]
でOK。
ふつうに構造体を関数に渡すときって*とかつけません
でしたっけ??
00141とは別人です
NGNGstruct object{ int x@`y@`z; };
int main(void) {
struct object array[10][10];
array[2][3].x = 3;
f((struct object*)&array);
return 0; }
void f(struct object *pt)
{ printf("%d\n"@`(pt+23)->x); }
こーゆーのって、やらない方がいい?
0015名無しさん@お腹いっぱい。
NGNGおいおい・・・・・・・ダブルポインタでどーしよっての?
struct s** xyの *xyがどこをさしてるの?まぁいいけど。
ポインタ配列をもっかい勉強し直しましょう。
>>13
そう。それが正解です。struct foo (*Foo)[10]でも通ります。
これは「struct fooと言う方の要素数10個の配列へのポインタ」です。
こいつの欠点は要素数10個の配列しかポインタ渡しできない点です。
>>14
一次元配列として扱わないといけないところがめんどいね。
0016ななしさん
NGNG渡せたとしたら、そこからうまくやるには
どう展開するといいんでしょう?
0017>1
NGNGただ、配列の値渡しは出来ないので、配列を渡したいときはポインタ
を渡すしか方法がありません。
2次元の配列の場合、n*mの配列を渡せないので、n個の配列への
ポインタを渡すわけです。だから13の方法も15の方法も使える
ってわけです。
00181
NGNGこれは2次元だけでなく多次元に対しても
同じと思っても大丈夫ですか?
0019名無しさん@お腹いっぱい。
NGNG0020名無しさん@お腹いっぱい。
NGNGarray[10][2][3][4][5]ってあったとき。
ようは、一番左端の要素数がここでは10でも20でもいいけど
他の要素数は変わっちゃだめ。
こういう、要素数の縛りが嫌ならポインタ配列を使えばいい。
多次元だとちと大変だけど、実用上、2次元まで知ってれば大丈夫でしょう。
0021名無しさん@お腹いっぱい。
NGNGfunc(struct object* pt@` int xlen){
// mとかnとかのループ
pt[xlen*n+m].x = 0; // pt[n][m]=0
}
struct object foo[10][10];
struct object boo[10][12];
main(){
func(foo@` 10);
func(boo@` 12);
}
とかやりたいときに使ってす。
0022Rockewell
NGNG{
printf("%d\n"@`((array + 2) + 3)->x);
}
main()
{
array[2][3].x = 5;
func(&array[0][0]);
}
0023名無しさん@お腹いっぱい。
NGNG2次元配列とポインタのポインタ(**のことね)は根本的に違うよ。
2次元配列の先頭アドレスはどちらかというとポインタ(*)に近い。
矢印書いて考えてみよう!
0024名無しさん@お腹いっぱい。
NGNGやっぱり、ポインタと配列についてちゃんと説明してる入門書が無いって
事なのかな・・・
ま、おやくそくなので、これを。
http://www.catnet.ne.jp/kouno/c_faq/c6.html
00252
NGNGいやぁ、他のスマートなやり方がでた今、遠吠えなんだけど>>2は、
#define X 2
#define Y 3
struct foo{
int a;
};
void func( foo** xy){
foo target;
for( int x=0; x<X; x++){
for( int y=0; y<Y; y++){
target = *(((foo*)(xy + x*Y)) +y);
}
}
}
main(){
foo xy[X][Y] = {0@`1@`2@`3@`4@`5@`};
func( (foo**)xy);
}
ってことが言いたかったんだわ。
特に多次元配列になるほど、完全にポインタで持ったほうが
融通も利くかなと思ったんだよ〜 汚いコードなんだけ。
多次元配列って、コンパイル時に大きさあたえてやらんと
添え字アクセスができないとか、一般性にかけるじゃん?
つーかまぁ、C++だと
vector< vector<foo>> xy;
とかでさくっと参照渡しすると何次元でも添え字使えて
楽勝でいいな。遅いけど。
0026>2
NGNG0027名無しさん@お腹いっぱい。
NGNG>foo xy[X][Y] = {0@`1@`2@`3@`4@`5@`};
>func( (foo**)xy);
だけみてわかるよ、でも、これって結構沢山のC入門者が引っ掛かってるんだろうね。
0028名無しさん@お腹いっぱい。
NGNG>foo xy[X][Y] = {0@`1@`2@`3@`4@`5@`};
構造体の要素が一個のときは、中を{}にしなくても
これで問題なし。多元配列に対して、リニアに要素を代入
するって点で、くだんの関数の中の処理と
対比させたつもりだったんだけど…
>func( (foo**)xy);
配列の配列をポインタのポインタで渡す。
これも一つのやり方。
>>12@`>>21みたく、全部一段階のポインタからリニアにアクセスする
よりは手間がかかるが、多次元配列の構造そのままにポインタで
アクセスする事をより強調する意味がある。
つまり、
>target = *(((foo*)(xy + x*Y)) +y);
これね。
0029名無しさん@お腹いっぱい。
NGNGstruxt MatrixX
{
int row@`col;
struct X *matrix;
};
とかしておいて
struct X *MatrixX_at(struct MatrixX *m@` int row@` int col)
{
assert(row >=0 && row < m->row);
assert(col >=0 && col < m->row);
return m->matrix[row*m->col+col];
}
とかするんでねーの?びろろ〜ん。
0030名無しさん@お腹いっぱい。
NGNGおれってば、蛇足でまちがってやがんの。
003127>28
NGNGだけじゃ判断できないけど
>foo xy[X][Y] = {0@`1@`2@`3@`4@`5@`};
と併せて見ると、この2行「だけ」みて解ってないのが解るってことさ。
struct foo{ double x; };
で実行してごらん。
00322>31
NGNG我ながら、かなりぼけた回答だった。
俺の負けだ。ありがとう。
0033名無しさん@お腹いっぱい。
NGNGって、ちゃんと代入されるし、
>func( (foo**)xy);
だけじゃ俺がアホか判断出来んっていってるのに、
なんで二つ合わさると俺がアホってわかるの?
ついでだから、種明かししてもらえませんか?
003431>33
NGNGint **では無い事はいい?
>func( (foo**)xy);
これを正しいとみると関数funcは、func(foo**p);だろう。
(もしfunc(foo*p);っていう関数に無理やりfoo**へキャストして渡してるとするならキャストのし方がおかしい)
そこで、xyの定義を見るとfooのx*y個の配列だ…
funcの呼び出しが正しいとすると、xy[0][0]はfooへのポインタってことになる。
そういうことだ。
00352>34
NGNG>int **では無い事はいい?
int*@` int (*)[20]@` int (*)[10][20]に関しては、理解にまったく問題は無いです。
ただ、int**で、2元配列の頭のアドレスはとれても、
それを、配列にアクセスするためのポインタ、の配列にアクセスするためのポインタ
として理解するのは、かなり型の意味をないがしろにしていたようです。
冷静に考えると、>>15が指摘しているように、
やっぱりポインタのポインタに過ぎませんでした。
多元配列は、配列の配列として理解して、
トップのアドレスから無理やりアクセスするよりも、
要素数の積のサイズの一次元の配列として考えた方が、
読みやすい上に、セーフティです。体で分かりました。
もしくはポインタを用いずに、最初から
func( int* xy[20]); あるいは
func( int xy [][10]);
と、2つめ以降は要素数の縛りに甘んじて、多次元の計算は
コンパイラにお任せするほうが良いです。
なにやら自己完結気味ですが、どうもありがとうございました。
アタマがひえました。
0036割りこみ
NGNGfunc(int *xy[20])
= func(int *xy[])
= func(int **xy)
なんだけどな。
正しくは
func(int (*xy)[20])
= func(int (*)[20])
これと同じじゃ。
http://piza.2ch.net/test/read.cgi?bbs=tech&key=965916840&st=121&to=126
00372>36
NGNG>>35はまたも誤りすぎで、書きたかったのは、
int (*xy)[20] (xyはintの要素数20の配列へのポインタ)
で、指摘の通り
int* xy[20];は、intへのポインタの要素数20の配列で、×っス。
これらのあやまりは
int *a;
より
int* a;
を好むところからきてるようです。
0038こまかいけど
NGNGxyはint型の要素数20の配列へのポインタ
>intへのポインタの要素数20の配列
xyはint型へのポインタを要素に持つポインタ配列
の方がいいかも。
>これらのあやまりは
>int *a;
>より
>int* a;
>を好むところからきてるようです。
・・・まぁ、人の勘違いは人それぞれだろうけど、
int (*xy)[20]とint **xyは全く別物の概念だから、
その説明では違和感がある。。。まぁ、ほんとどうでも良いけど。
0039ななしさん
NGNG配列の構造体で特定のメンバだけを関数に渡したいとき
はどうすればいいですか?
0040名無しさん@お腹いっぱい。
NGNGstruct kouzou hoge;
// 構造体kouzou型変数hogeのメンバーである
// 配列arrayの先頭アドレスを関数fooに渡す。
foo(hoge.array);
で良いと思うけど。。。
0041おれもこまかいけど
NGNG20個ってのがどっか行っちゃってるけど…
004238>41
NGNG関数へ渡すことだけに絞ればポインタ配列では20は重要ではない。
関数ないでオーバーランしたらどうするっていう、
つまらんつっこみは削除。
004338
NGNG>>36
> = func(int *xy[])
> func(int (*xy)[20])
を見て下さい。20が無ければいけないのと無くてもいいのとあるでしょ。
0044はあ?
NGNG0045あの・・・
NGNGんですけど・・・
004638
NGNG0047しかし
NGNG00483
NGNG0049名無しさん@お腹いっぱい。
NGNG話を蒸し返すようで申し訳ありません。
構造体の2次元配列を別の構造体に持たせて,
その参照(アドレス)を関数の引数にしてはどうでしょうか。
この方法ですと,おかしなキャスティングとは無縁です。
#define&nsp;SIZE&nsp;10
struct&nsp;ThreeDimension&nsp;{
&nsp;&nsp;&nsp;&nsp;int&nsp;x@`&nsp;y@`&nsp;z;
};
//&nsp;構造体(ThreeDimension)の2次元配列をもつ構造体
struct&nsp;matrix&nsp;{
&nsp;&nsp;&nsp;&nsp;struct&nsp;ThreeDimension&nsp;element[SIZE][SIZE];
};
//&nsp;何らかの処理をする関数
void&nsp;calculate(struct&nsp;matrix&nsp;*o)&nsp;{
&nsp;&nsp;&nsp;&nsp;for&nsp;(int&nsp;i&nsp;=&nsp;0;&nsp;i&nsp;<&nsp;SIZE;&nsp;i&nsp;++)&nsp;{
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;for&nsp;(int&nsp;j&nsp;=&nsp;0;&nsp;j&nsp;<&nsp;SIZE;&nsp;j&nsp;++)&nsp;{
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;o->element[i][j].x&nsp;=&nsp;1;
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;o->element[i][j].y&nsp;=&nsp;1;
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;o->element[i][j].z&nsp;=&nsp;1;
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;}
&nsp;&nsp;&nsp;&nsp;}
}
int&nsp;main()&nsp;{
&nsp;&nsp;&nsp;&nsp;struct&nsp;matrix&nsp;o;
&nsp;&nsp;&nsp;&nsp;for&nsp;(int&nsp;i&nsp;=&nsp;0;&nsp;i&nsp;<&nsp;SIZE;&nsp;i&nsp;++)&nsp;{
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;for&nsp;(int&nsp;j&nsp;=&nsp;0;&nsp;j&nsp;<&nsp;SIZE;&nsp;j&nsp;++)&nsp;{
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;o.element[i][j].x&nsp;=&nsp;0;
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;o.element[i][j].y&nsp;=&nsp;0;
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;o.element[i][j].z&nsp;=&nsp;0;
&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;&nsp;}
&nsp;&nsp;&nsp;&nsp;}
&nsp;&nsp;&nsp;&nsp;calculate(&o);
&nsp;&nsp;&nsp;&nsp;return&nsp;0;
}
005049
NGNG0051>49
NGNGstruct A { int x[10][10]; };
foo( struct A* ap) { ap->x[a][b]; }
int main() { struct A a; foo( &a); };
すっきりしてる。
0052名無しさん@お腹いっぱい。
NGNG0053名無しさん@お腹いっぱい。
NGNGdouble* a;
int h;
int w;
double& operator()(int i@` int j){
return a[i*w + j];
};
}m;
これで
m[1][2]じゃなくてm(1@`2)でアクセスしたら関数での2重配列もどきなら作れます。
どうですか?
0054名無しさん@お腹いっぱい。
NGNGこのクラスをどのようなプログラムで使うかに依るのですが,
普通メソッド呼び出しはコスト高になります(処理速度が犠牲になる)。
ですから,頻繁にメソッド呼び出しが発生してかつ処理速度を重視する用途には適しませんが,
そうでなければ使っても問題ないと思います。
ただし今回のお題は「行列」を処理するプログラムですので,どちらかというと処理速度を優先すべきだと思います。
またプログラムで行列の成分にアクセスするときは,慣習的にa[i][j]といった表記の仕方をします。
ですからよっぽどの理由がないかぎりこの慣習に従うようにして,自己流の表記方法はなるべく使わない方が良いです。
#複数人で作業しているときはなおさら。
大事なことは,だれが読んでも分かるプログラムにすることです。
0055名無しさん@お腹いっぱい。
NGNG[][]の関数形ってなんですか?
operator[][]() ですかね?
わかんな〜いね。
0056>55
NGNGhoge[][]のhogeとhoge[]では型が違いますから
それぞれの型についてoperator[]()を定義してください。
005753
NGNG処理速度を考えた場合どれくらいの負荷になるのかなぁ?とは、
思っていたのですが、実際に計測したことはなかったです。
やっぱり負荷は高いですか。
ですが、このようなクラスを作った場合にメリットは、
普通の配列のようにメモリへの不正アクセスを防げたり、
2重配列を3D処理で用いられる行列として考えた場合、
掛け算などオーバーロード(例えば~MはMの転置行列)が
利くので、プログラムの可読性は高くなります。
だけど、やっぱ負荷が高いと使えないですね。
>55さん
[]の2重でのオペレーターはつかえません。
使うなら同じようにm[1@`2]と言う風になります。
ですが()でオーバーロードした方が、
オブジェクトの配列の区別がつきやすいような気がします。
まぁどっちでもかまいませんが。
0058名無しさん@お腹いっぱい。
NGNGそのために参照を返すんでしょ?
005953
NGNGなるほど。
今、確認したらm[1][2]って感じでアクセスできました。
オーバーロードはなかなか面白いですが、
いろんな勘違いの元になるので意見が分かれるところだと思いますが。
006053
NGNGoperator[][]
っていうのができないと言ったつもりだったんですが、
当然すぎましたね。
006158
NGNG006258
NGNGあるクラスの[]をオーバーロードするのと、あるクラスの配列とを勘違い
してました、べんきょーしなおしてきます。
006353
NGNGpublic:
double* d;
void init(int j@` double* a){
d=new double[j];
for(int k=0; k<j; k++){
d[k]=a[k];
}
}
double& operator[](int i){
return d[i];
}
};
class matrix{
public:
p_double* p;
void init(int i@` int j@` double* d){
p=new p_double[i];
for(int k=0; k<i; k++){
p[k].init(j@` d);
d+=j;
}
}
p_double& operator[](int i){
return p[i];
}
};
main(){
matrix m;
double a[16]={ 1@`2@`3@`4
@`5@`6@`7@`8
@`9@`10@`11@`12
@`13@`14@`15@`16
};
m.init(4@` 4@` a);
m[1][2]=123;
}
こんな感じでしょうか。
プログラミング1年目なんで変なところとか、
いろいろ指摘してください。
006453
NGNGpublic:
double** p;
void init(int i@` int j){
p=new double* [i];
for(int k=0; k<i; k++){
p[k]=new double[j];
}
};
double* operator[](int i){
return p[i];
};
};
こっちのほうがいいですね。
あぁ、Cの配列の話題のはずなのに、半分あらしっぽくなりました。
ごめんなさい。
006553=64
NGNGやっぱ63がいいかなぁ。
なんだか眠いぞ。変な事いってそうだ。
もうねます。
006658
NGNGint c[20][20]をint[400]にして、return( c[m*20] );でもいいかも。
ただし、foo::operator[]は1どしか呼ばれないので、範囲チェックとか
はできません。そういう場合は53さんの(56さん指摘の)方法しかないのかな?
class foo{
public:
int c[20][20] ;
int * operator[](int m){
return( &c[m][0] ) ;
} ;
} ;
void main(void){
foo F ;
F[2][1] = 100 ;
cout << F[2][1] ;
}
006758
NGNGさて、仕事しよう、っと。
006853=63=64=65
NGNGある程度完成したら、
クラスの中身を64にかえて使うのはありか?
006953=63=64=65
NGNGお互い、同じタイミングの書き込みでおもしろいです。
007058
NGNGおもしろいですね、なんか、CHATみたいで(^^
結局テンプレート使うのが一番ええのかな、などとも思ったり、
int* at(idxX@` idxY) とかがいいのかな、とも思ったり、
get() set() がいいかなと思ったり(苦笑
0071名無しさん@お腹いっぱい。
NGNGa[1@`2@`3]って感じでできるらしいぞ。
0072名無しさん@LV2
NGNGははぁ、それ簡単でよさそうだなぁ。
■ このスレッドは過去ログ倉庫に格納されています