• ベストアンサー

構造体のアドレス渡し

構造体をmain()からアドレス渡しで別関数(test.cpp)に渡し、その関数の中だけでの別関数test1()にその構造体を、値渡しでもアドレス渡しでも、渡せるのでしょうか? ちなみにmain.cppと、test.cppと、myhead.hとして分割コンパイルでやりました。 /*---------main.cpp--------*/ //ヘッダファイルで構造体宣言、test()のプロトタイプ宣言済み void main() { struct data dt[10]; ・・・・・・ test(dt); //test.cppのtest関数に構造体を渡す。 } /*---------test.cpp---------*/ void test1(??????); //test1()のプロトタイプ宣言 void test(struct data *p) //構造体をアドレス渡しで受け取った { ・・・・・ test1(?????); //test.cppで宣言したtest1関数に構造体を渡したい } どうかよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

構造体だと考えるからややこしく思えるのです。 構造体でなく、単なるintで考えてみて下さい。Cにとっては「引数に渡せる物」は構造体もintも一緒です。 void main() { int dt[10]; ・・・・・・ test(dt); //test.cppのtest関数にintを渡す。 } /*---------test.cpp---------*/ void test1(int para); //値渡しtest1()のプロトタイプ宣言 void test2(int *para); //アドレス渡しtest2()のプロトタイプ宣言 void test(int *p) //intをアドレス渡しで受け取った { ・・・・・ test1(*p); //test.cppで宣言したtest1関数にintを値で渡したい test1(p[0]); //こう書いても同じです test2(p); //test.cppで宣言したtest1関数にintをアドレスで渡したい test2(&p[0]); //こう書いても同じです } 上記の「int」を「struct data」に置き換えても、Cは同じ事をします。 test1には「値が1つだけ」渡ります。渡るのは配列の1つの要素だけです。0~9番目をまとめて全部渡す事は出来ません。 test2には「アドレス」が渡ります。渡るのは配列の先頭アドレスなので、アドレスを元に0~9番目にアクセス出来ます。 「配列の10個の要素をまとめて値渡ししたい」と言う場合は、その配列をメンバにもつ構造体を新たに定義し、配列をラップした構造体で値渡ししましょう。

sikimori
質問者

お礼

御回答ありがとうございます。 確かに"構造体で"という考えにしばられていました。 試してみましたら思い通りに動きました。 的確なアドバイス、ありがとうございました。

その他の回答 (4)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

> どういったやり方(書き方)で渡せるのか知りたかったので。 ファイル名から察するにC++でしょうか? mainの返却値の型がvoidなので、非標準処理系か規格合致自立処理系ですね。非標準処理系の場合は分からないので、規格合致自立処理系だと解釈して回答します。 まず、アドレス渡しというのは正確には存在しません。存在するのは「ポインタ渡し」と「参照渡し」です。質問文で挙げられているのはポインタ渡しですね。 「どういったやり方」を回答する前に、まずは用途について考えてみましょう。 単に値渡しより効率がよいからというだけの理由であれば、ポインタ渡しにするより(const修飾付きの)参照渡しにする方が得策です。その場合、 void test1(const data& r); void test(const data& r) {  ...  test1(r);  ... } とします。 配列ごと参照で渡したいのであれば、 void test(const data (&r)[10]) のようにするとよいでしょう。配列の要素数をハードコーディングしたくないのであれば、 template<std::size_t N> void test(const data (&r)[N]) とすれば、要素数が変わってもそのまま使えます。 要素数が動的に変わるのであれば、std::vectorクラステンプレートの使用を検討することをお勧めします。あるいは、Boost C++ Librariesが利用できるのであれば、boost::arrayクラステンプレートを、TR1ライブラリが利用できるのであれば、std::tr1::arrayクラステンプレートを使用してもよいでしょう。 なお、CとC++で共用するのであれば、#4さんの回答のように、サイズを別に渡した方がよいと思います。 次に、空ポインタを渡す可能性があるからポインタ渡しにするのであれば、やはりconst修飾した上で、 void test1(const data* p); void test(const data* p) {  ...  test1(p);  ... } とすることになります。あるいは、先に紹介した参照渡しと、引数なしの2種類を多重定義してもよいでしょう。 なお、ポインタ渡しの場合でも、配列へのポインタとして渡すことも可能です。 void test(const data (*p)[10]) あるいは、 template<std::size_t N> void test(const data (*p)[N]) のようにです。 渡した構造体の内容が、呼び出し先の関数で書き換えられるのであればconst修飾子を付けることはできませんので外してください。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.4

本題とは少し離れますが、配列を関数に渡す場合に その配列のサイズを渡すほうが良いと思います。 でなければ、関数内で配列にアクセスする場合、 どこまでアクセスして良いのか分からなくなります。 特に今回のように、関数内で定義された配列のサイズは 呼び出し元しかそのサイズを知る明確な方法がありません。 サイズをつけることで、アクセスできる範囲を明確にし、 さらに、引数を見るだけでポインタが、 単なるポインタを要求しているのか、 配列へのポインタを要求しているのかの区別が容易になります。 今回の場合だと >void test( struct data *p)    ↓ void test( stuct data *p, size_t size ) など。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★確かに『出来ます』はい。 ・構造体のポインタをそのまま渡すとアドレス渡しですよね。  だから『*』演算子を使えば構造体の実体を意味しますのでこれを渡せばよいだけです。  回答者 No.2 さんのアドバイスを引用すると >構造体でなく、単なるintで考えてみて下さい。 >Cにとっては「引数に渡せる物」は構造体もintも一緒です。  その通りです。すごく分かりやすいです。 ・上記のを踏まえると下のサンプルのようになります。 サンプル: int main( void ) {  struct data dt[10];    test1( dt ); ←ここは当然アドレス渡し  return 0; } // test.cpp の test1() 関数 void test1( struct data *dt ) {  sub1( dt ); ←これはアドレス渡し  sub2( *dt ); ←これが値渡し } // アドレス渡しの関数 void sub1( struct data *dt ) {  : } // 値渡しの関数 void sub2( struct data dt ) {  : } 最後に: ・構造体のポインタを特別扱いしないで普通の単純変数(int*,long*,double*)のポインタと  同じような考えで行えるのです。  ちなみに構造体のポインタのメンバ参照は  (1)tag->member  (2)(*tag).member  の両方とも正しくアクセスできますが(2)はなぜ『.』演算子でアクセスできるかが分かれば  『*』演算子の使い方が分かってくると思います。 ・以上。

sikimori
質問者

お礼

いつも御回答下さりありがとうございます。非常に助かっています。 アドレス渡しされたものを、さらにアドレス渡しするというのは、 考え方がややこしいのでおおよそ不可能だと思っていました。 ありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

できます。

sikimori
質問者

補足

言葉足らずでした。すいません。 どういったやり方(書き方)で渡せるのか知りたかったので。