- ベストアンサー
ポインタのポインタを使った書き換えがうまくいかない
- 自作の関数の一部分をポインタのポインタを使って書き換えた結果、プログラムが強制終了するようになりました。
- ポインタのポインタを使って書き換えることで処理速度を向上させようとしましたが、うまくいかない問題が発生しています。
- 関数の抽象的な部分にあたるコードの一部を示しましたが、どこが間違っているのかわかりづらい状況です。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
繰り返しになるのですが p_part = &(st.part[start]); とすると *p_part の値を変更する、ということは st.part[start] の値を変更することになります。 *p_part += st.x; は st.part[start] += st.x; (*p_part) ++ は は st.part[start] ++ です。 もとの st.part[start] = malloc~ として確保したアドレスが 0x1000 だったとします。 この0x1000が st.part[start][0]の収納されるアドレスとなります。 0x1001が st.part[start][1]の収納されるアドレスとなります。 ここで st.part[start] += st.x とすると、 アドレスが 『0x1000+st.x』に変わります。 st.part[start][0]のアドレスは『0x1000+st.x』になります。 free(st.part[start])としても 0x1000からの解放ができません。 この処理を2度3度と繰り返せば、どんどんst.part[start]の値がズレていきます。 そのうちmallocで確保した範囲をはみだすでしょう。そうなれば、領域範囲外への不正アクセスでエラーになる可能性があります。
その他の回答 (1)
- kmee
- ベストアンサー率55% (1857/3366)
> *p_part += st.x; p_part = st.part+start なら *p_part ⇔ st.part[start] ; です。 *p_part += st.x とすれば、 st.part[start] (に記録されているポインタ)自体が +st.xされます。 つまり、以降はst.part[start][0]が、以前の st.part[start][st.x]になります。 参照先に影響を与えないのはポインタ変数だけです。(今回の例なら p_part, p_pa ) *,->で実体にアクセスすれば、その実体に影響を与えます。 今回の例で言えば unsigned char * p_dst = &(st.part[start][st.x]); // アドレスであることをわかりやすく書いてみた。 // unsigned char * p_dst = (st.part[start]+st.x); // unsigned char * p_dst = *(st.part+start)+st.x; // などとも p_pa = pa;//unsigned char * 型 for(j = 0; j < jM; j++){ *(p_dst ++) |= *(p_pa++) << mod; } // ただ、処理速度向上にどこまで役立つかは不明。 // 特に昨今のコンパイラなら素直に書いて、 // コンパイラの最適化に任せた方が保守性はいいかも。 for(j = 0; j < jM; j++){ p_dst[j] |= p_pa[j] << mod; } とか for(j = 0; j < jM; j++){ *p_dst |= *p_pa << mod; p_dst ++ ; p_pa ++; }
お礼
ご回答ありがとうございます。 確かに >> unsigned char * p_dst = &(st.part[start][st.x]); のように書くと分かりやすいですね。 このように書き直してプログラムを実行したところ、この関数の実行速度は Visual C++ の場合は100000回が1.5秒から0.89秒に Borland C++ 5.5.1 の場合は0.70秒から0.28秒 になり、かなり改善されたようです。構造体を用いているからかもしれません。 VC++よりBorlandのほうがずっと速いことは意外でしたが。 ところで、結局(B)のプログラムのどこが問題であるのかいまいちわかりません。 >>参照先に影響を与えないのはポインタ変数だけです。(今回の例なら p_part, p_pa ) *,->で実体にアクセスすれば、その実体に影響を与えます。 の部分がよくわからなかったのですが、これが関係しているのでしょうか? よろしければ、さらに回答を頂ければ幸いです。
お礼
分かりやすい回答ありがとうございます。 st.part[start][0]のアドレスを書きかえないように //(B) p_part = st.part + start; //unsigned char ** 型 p_pa = pa; //unsigned char * 型 ep_part = *p_part + st.x; //unsigned char ** 型 for(j = 0; j < jM; j++){ *(ep_part++) |= *(p_pa++) << mod; //(*) } のようにしたところ、うまくいったようです。 速度もほんのわずかですが、より速くなりました。 大変参考になり、理解を深めることが出来ました。 本当にありがとうございます。