割り当てた配列の情報を構造体に記録する例 ========================================= 今までは割り当てたメモリ領域の先頭アドレスだけをポインタ変数で保持していました が、配列領域の長さも変数で記録しておくと便利なことがあります。ポインタと長さを セットで覚えておくために、構造体かクラスを使うことができます。 この例では、歴史的に古くからある構造体を用いて、C言語風に実装しています。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 1 :lines: 1-12 まず構造体 ``Array`` を定義しています。 ``Array`` という型がこれで定義されるの で、 ``Array`` 型の変数を定義できるようになります。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 14 :lines: 14-22 ダミーデータを設定する ``set_dummy_data_struct`` 関数では Array型のポインタを受 け取ります。このポインタが指している ``Array`` のデータ中に、配列データのポイン タと、配列の要素数が記録されています。 ``par->n_size`` のようにして、ポインタが指している構造体のメンバ変数にアクセスします。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 24 :lines: 24-30 データをコピーする関数ではArray型のポインタを2つ受け取ります。 コピー元の ``psrc`` には const がついています。そのため ``psrc`` が指している構 造体のメンバ変数は代入禁止になります。ただし、そこからさらに先は代入禁止ではあり ません。 - ``psrc->n_size`` : 代入禁止 - ``psrc->pdata`` : 代入禁止 - ``psrc->pdata[i]`` : 代入可能 これでは、constの意味が不完全です。本来は「コピー元の ``psrc`` の中身は改変しな い」という約束のためにconstを付けているのに、配列の中身のデータについては書き換 えることができてしまいます。 この点はC++の言語仕様で割り切られている点だと思います。これでも一定の意義は果た せます。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 32 :lines: 32-54 配列の内容を印字する ``print_data`` は、 ``Array`` を受け取る版と、配列の先頭ア ドレスを受け取る版の2つを用意しています。後でmain関数を見ると、それぞれを呼び出 す処理が登場します。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 56 :lines: 56-75 配列の割り当ては ``allocate_array_struct`` 関数で行っています。引数の ``**ppArray`` は ``Array`` 型のポインタのポインタです。処理は、 ``Array`` のメモ リ割り当てと、その先の配列データのメモリ割り当ての2段構えになっています。 ``free_array_struct`` では2段構えでメモリを解放しています。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 77 :lines: 77-90 ``main`` 関数では配列を割り当てた後に個々の関数を呼んでいます。 ``allocate_array_struct`` 関数の呼び出しにおいては ``Array`` のポインタ変数 ``parray`` に対して ``&parray`` と書いて変数のアドレスを取得しています。「変数 parrayのアドレスはここだから、結果をこのアドレスに書き込んでください」というよう に引数として渡しています。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 92 :lines: 92-98 配列の先頭アドレスを要求する関数 ``print_data`` を呼ぶときは、 ``Array`` の先頭 アドレスではなくてその先の配列データの先頭アドレス ``parray1->parray`` を渡して います。 .. literalinclude:: s003.cpp :language: c++ :linenos: :lineno-start: 100 :lines: 100-114 ソース全体は以下のようになります: .. literalinclude:: s003.cpp :language: c++ :linenos: :download:`Download the source code` 実行例を示します:: % ./s003 s003 Before initialization [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] After initialization [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] After array copy [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]