
VisualC++2008
の、Windowsフォームアプリケーションを使用しています。
自作クラスの中に組み込む線形リスト的なものを、後で移動したりする場合実体のコピーをしなくて済むよう
今、「アドレス」を格納する配列を作りたいです。
しかし、ポインタのポインタに対して色々実験してみたのですが
どうもあと一歩ぐらいのところで手が届きません
フォームのイベントで、試しに以下のように書いてみると
Text = "";
char *a[8], b =7 ,*c = new char[7], i =7;
while (i) { c[i] = --i; a[i] = &c[i]; }
a[7] = &b;
while (i<8) Text += *(*a+i++);
delete c;
これを実行したとき
フォームのTextが
「01234567」
となってほしいのですが
「0123456-3」
となってしまいます。
試してみたのですが
その直後にbを調べると、やはりちゃんと7になっており
また
a[7] と &b をifおよび==を用いて比較してみても
同じになっています。
なお、この-3というのはどうも、解放処理の後でそこにアクセスした場合はこの場合
「-35」
となり、確保中の時に代入してないアドレスにアクセスすると
「-3」
となるような感じです。
このような、連続していないアドレスへの参照を配列化しておいて取り出す事は出来ないのでしょうか?
No.2ベストアンサー
- 回答日時:
えぇと, 「配列的な書き方」とか「ポインタ的な書き方」ってのは厳密に区別する必要はないと思いますよ. 今どきのコンパイラなら (それなりな最適化オプションをかければ) 同じコードにするはずですから, プログラム上で読みやすい書き方をすべきでしょう.
でフォームの話はやったことないので見なかったことにして (<ぉぃ), 未定義動作関係の話だけします.
c[i] = --i;
という文が未定義動作になるのは, 直接的には「オブジェクトの値を変更する場合, その値は新しい値を決めるため以外に使ってはいけない」という規定によります. 今の例に即してもっとかみくだいていうと「右辺のデクリメントがどのタイミングで実行されるか確定していない」ことと「左辺と右辺のどちらを先に計算するかが定まっていない」ことの 2点が問題になります. つまり, コンパイラはこの文を (例えば)
--i, c[i] = i;
と解釈してもいいし
c[i] = i-1, --i;
と解釈してもかまいません (未定義動作なので「全く関係ない動作」を含む他のどのような解釈もありうるが).
... あれ?
*(*a+i++)
って,
(*a)[i++]
と等価ですよね....
*a[i++]
と等価にしたいなら
**(a+i++)
では?
ありがとうございます。
えっと、そこなんですが・・・
私は基本的に、式というのは右から左へ実行されるはずだと思っていました。
しかし
インクリメント、デクリメントが含まれる場合は、つまりそういう感じに微妙になる、ということでしょうか?
**(a+i++)
でできました!
ありがとうございます。
ちょっと私は内容の趣旨を勘違いしていたかもしれません。
下のを変形させてみると(これもできました)私がやりたかった事はこんな感じの事です。
Text ="";
char **a=new char*[8], *d[8], b=7 ,c[7], i=7;
char *f =c+7 ,**g =a+7, **h =d;
a[7] =&b;
while (i) { *--f =--i; *--g =f; }
for (;i<8;i++) *h++ = *g++;
delete a;
while (i) Text +=*d[--i];
こういう事ならば、毎回iの値を確認しなくてすむので、そういう比較においてはこちらの方が高速ですよね?
No.4
- 回答日時:
ガイドラインを読んでみて、これだけなら問題ないはず・・・?
と思ったので、連絡・状況整理用に別IDで回答欄を使わせてください。
質問者です。
「質問・問題の解決につながる投稿」ですので、種類は「回答」にさせていただきます。
ちゃんと前置・後置という言葉があるんですね。
今回の質問は大丈夫そうなので締め切りとさせていただきます。
そして、残っている2点についてかなりかみ砕いて新質問を立てました。
後で見て分かりやすいようにここにリンクをはっておきますので、よろしければよろしくお願いいたします。
一時的なポインタを作る場合との速度比較についてです
http://oshiete1.goo.ne.jp/qa4645062.html
インクリメント、デクリメントの順序について
http://oshiete1.goo.ne.jp/qa4645073.html
No.1
- 回答日時:
あ, とりあえず
c[i] = --i;
という文は未定義動作となるので書いちゃダメです.
そこが問題となっている可能性はありませんかね.
この回答への補足
・・・ってよく考えたら
**a+i++
は、違いますね。
やり方の問題で一見結果としては同じに見えただけで、これでは単に*c+i++と同じ事ですよね(苦笑)
c[i] = --i;
を
c[i] = --i+1;
などとやってみたら
12345678
になってしまいました。やはり違う。
しかし
*a[i++]
ならば間違いないようです
12345677
と、正しい解を出せました!
うーむ、しかし配列的な書き方しか出来ないのは最速処理は出来なく、悔しいので、ポインタ的書き方が2重ポインタで出来るならそっちも知りたいです。
ありがとうございます。
なんか教えて!gooに投稿してみたら思ったより見にくくて・・・
申し訳ありません
この右側は、実際には先行デクリメントっていうのかな・・?
です。
もしそれでもNGということならば
知っておきたいです。
どういう風に未定義動作扱いになるのでしょうか?
こちらでやっている分には、そういう事をやる分だけには問題なく、ビルドは出来、ちゃんと先にiが-1されてからiがc[i]に格納される
という風に、動作も出来るようです。
2個目のwhile文の中身の右辺の部分の括弧を外す、つまり
**a+i++;
てやったら出来ちゃいました。
にゃんかムズイですね。
ここも配列っぽく書くと
*a[i++];
ってなりますが、こちらでもできました。
さらに
受け渡しは出来るのか確認するべく、ちょいと改造して新たな実験をしてみました。
Text ="";
char **a=new char*[8], *d[8], b=7 ,c[7], i=7;
while (i) { c[i] =--i; a[i] =&c[i]; }
a[7] =&b;
for (;i<8;i++) d[i] =a[i];
delete a;
while (i) Text +=*d[--i];
結果は、ちゃんと
「76543210」
になりました。
ただ、これで本当に合ってるのかどうか…というと、ちゃんと把握できてないのでちょっと不安です
これは、ちゃんとaからdにアドレスの配列を受け渡せた、って事でOKでしょうかね…?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- C言語・C++・C# C言語 配列とポインタについて 2 2022/06/02 11:53
- その他(プログラミング・Web制作) pythonにおける単方向リストの実装について 4 2022/07/13 12:34
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
- Visual Basic(VBA) ExcelからAccessのテーブルに書き込む時に時間がかかる 1 2022/10/14 20:38
- Excel(エクセル) Excel VBAについてです。 少しだけ知識はあるのですが、 うまくいかなかったので 質問させてい 3 2022/09/13 18:40
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
ExcelVBAでのkernel32(64bit)
-
ファイルポインタのヘッダーフ...
-
Run-Time Check Failure #3とい...
-
参照型で受け取った引数をポイ...
-
C言語 プログラミングの問題 ...
-
DLL<->VB間での受け渡し(文字...
-
TCHAR文字列内の検索について
-
c言語で任意のファイルから読み...
-
基本アルゴリズムの『返す』の...
-
ポインタのポインタについて
-
cv::Mat から vectorにコピー
-
構造体内のポインタのポインタ...
-
メモリのアドレスからの値の取...
-
fopne で失敗する原因
-
型変換について
-
C++とWIN32APIとゲームプログラ...
-
CopyMemory()をmemcpy()に書き...
-
関数にポインタを渡して動的確...
-
ThinkPad ポインタが勝手に動...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
init関数の意味
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
Run-Time Check Failure #3とい...
-
ExcelVBAでのkernel32(64bit)
-
LPSTR型の初期化について
-
参照型で受け取った引数をポイ...
-
アプリを32bitから64bit移行
-
c言語で任意のファイルから読み...
-
関数ポインタの利点
-
コンストラクタでnewを失敗した...
-
ハンドルはポインタか
-
ポインタについて
-
C++で関数ポインタから関数名を...
-
基本アルゴリズムの『返す』の...
-
無効なポインタ操作のエラー
-
[C言語] NULLは必ず0(番地)です...
-
関数にポインタを渡して動的確...
おすすめ情報