
不具合が生じ、業務ソースのエラー処理の部分まで掘り進んで見ていたら、
トリプルポインタ(ポインタのポインタのポインタ)を使用している部分がありました。
外注で中国産のソースのようで、当人に聞くことはできず、
周りの知識人に聞いてみたのですが「それでうまく動いているんならいいんじゃないの?」と
素っ気ない対応でした。
トリプルポインタが必須となる状況はあるのでしょうか?
構造体がネストしていてそのメンバに文字列があって…
となっている場合などでもダブルポインタ(ポインタのポインタ)で処理できるように思います。
そんなときにトリプルポインタを使うよっていう状況やサンプルがありましたら教えてください。
よろしくお願いいたします。
ちなみに、不具合は単純なものですぐに解決しました。
A 回答 (6件)
- 最新から表示
- 回答順に表示
No.6
- 回答日時:
C では void * とその他のポインタ型の間でキャストなしに値のやりとりをすることができます. で malloc のプロトタイプは
void *malloc(size_t)
ですから, もともと「返り値を int * (など) にキャストする必要性」はないんです. プログラミングスタイルとしてキャストしているだけ, でしょう.
C++ では「void * への変換」はキャストなしで OK ですが「void * からの変換」には明示的なキャストを要求されます.
No.5
- 回答日時:
double の 3次元配列は
array[x][y][z]
でアクセスしたいし, そうすると
array[x][y][z] が double
→ array[x][y] は double *
→ array[x] は double **
→ array は double ***
になるのが「自然」でしょ, ってこと.
もちろん #4 のように
array[(x*SIZEY + y)*SIZEZ + z]
でアクセスしてもいいけど, あんまり自然って感じがしない. メモリ効率はいいんだけどねぇ.
ちなみに個人的には
int *p = (int *)malloc(sizeof(int) * n);
よりも
int *p = malloc(sizeof *p * n);
の方が好き.
ご回答ありがとうございます。
三次元配列の例は具体的でわかりやすかったです。
やっぱりメモリ上でどう確保されて、どうアクセスするかがイメージ出来ていないといけないんだなと思いました。
またうちの会社では
int *p = (int *)malloc(sizeof(int) * n);
一本ですね。もうひとつの書き方は初めて見ました。この書き方だとint*型にキャストする必要がないんですね。
まだまだ勉強しないといけないことがたくさんあると感じるご回答でした。
これからも勉強していこうと思います。
また、お礼が遅れまして失礼しました。
No.4
- 回答日時:
例えば
画像は二次元配列で実装すると便利です。
画素をPIXEL型とすると、変数imageに動的確保するには
PIXEL ** image = (PIXEL **)malloc(sizeof(PIXEL *)*HEIGHT); /*(1)*/
for( y=0 ;y<HEIGHT;++y ){
image[y] = (PIXEL *)malloc(sizeof(PIXEL)*WIDTH); /*(2)*/
}
とするのが常套手段の一つです。ここでPIXELへのポインタへのポインタが使われます。
横1列分のPIXELの配列を、高さ分用意します(2)。それを収めるのに、PIXEL *の配列を用意します(1)。
このimageを参照渡しして、別の画像に書き換えたり、解放してNULLを代入したりするような関数を作るなら、引数の型は PIXEL ***になります。
この画像を複数枚使いたければ、image1,image2...と変数を用意するのもよいですが、 PIXEL ** の配列として用意するのが普通です。PIXEL ** の配列は PIC *** と同等です。
そして、動的に確保するなら
PIXEL *** images = (PIXEL ***)malloc(sizeof(PIXEL **)*NUM_OF_IMAGES);
です。
特定の画素を利用する場合は images[画像番号][Y座標][X座標」 と三次元配列のようになります。
また、画像番号=Z座標と考えれば、立体と見做せます。
*が並んでややこしく思えますが
typedef PIXEL * HLINE ; /* PIXELの列がHLINE */
typedef HLINE * IMAGE ; /* HLINEの列がIMAGE */
として
LINE *image = (LINE *)malloc(sizeof(LINE)*HEIGHT);
IMAGE *images = (IMAGE *)malloc(sizeof(IMAGE)*NUM_OF_IMAGES);
とすれば、見慣れた形ではないでしょうか。
逆に
typedef COLOR_INFO * PIXEL ; /* PIXELは色情報へのポインタ */
となっていたら、COLOR_INFOで表記すれば
COLOR_INFO ****images = (COLOR_INFO ****)malloc(sizeof(COLOR_INFO ***)*NUM_OF_IMAGES);
と*が1こずつ増えて「クアドラプルポインタ?」になります。
/*
余談:
実際には、画像は幅x高さの1次元配列として実装し、(X,Y)は[ Y * WIDHT + X ]でアクセスする、という場合も多いです。
*/
ご回答ありがとうございます。
そろそろ家を出なければならず時間がないので書いていただいたソースをきちんと
読んで理解できていませんが、お礼を。
ポインタのポインタを扱う情報が複数あるので、それを個別にmallocしていてはメモリ上で飛び飛びの位置に領域が確保される可能性があるので喜ばしくはない、
なので最初から複数情報分まとめてmallocすれば、複数情報がメモリ上で連続した領域に確保され好ましい、かつ、配列としてアクセスできる、ということでしょうか。
仕事でソースを見ていて、
>image[y] = (PIXEL *)malloc(sizeof(PIXEL)*WIDTH); /*(2)*/
>PIXEL ** image = (PIXEL **)malloc(sizeof(PIXEL *)*HEIGHT); /*(1)*/
の例にだしていただいたように、mallocの前に*がひとつだったり**だったりするのが
混在していて、その意味を読み取れずに混乱しています。
ですので?、mallocで確保した構造体領域を開放するのに、間違ったFree()の使い方をしてメモリリークにしたりしてしまっています。。
市販のよくあるテキストではポインタの基礎概念と文字列(配列と等価)へのポインタ、参照渡しと値渡しの仕組みなどが説明されているものが多いのですが、
二次元配列(や三次元配列)、構造体への配列、鬼門のmallocとの関係を詳細に解説してあるテキストに巡りあえずにいます。
配列、値渡し、参照渡しはわかりますが、それが応用されるととたんに「?」です。。
やはり、地道に自分でコードを書いて勉強していくしかないのでしょうか。
一年以上Cで(下働きですが)業務していてまだこんなこともわからないのかと思うと悲しくなるものがあります。
「クアドラプルポインタ(なんてものも理屈上は可能ですね)」が出るようなソースになっても、それなりにスラスラと理解できる読解力を身につけたいです。
地道にテキストを購入して自作ソースで勉強させていただきます。
書籍については別途質問を立てましたので
http://oshiete.goo.ne.jp/qa/6481380.html
もしおすすめの書籍などがありましたらよろしくお願いいたします。
実例ソースを書いていただきまして誠にありがとうございました。
No.3
- 回答日時:
念のため補足:
#2 の「C99 の~」は
C99 の言語仕様上, そもそも「ポインタのポインタ」を使わないと決してプログラムが作れないということはない
という意味です. ライブラリに「ポインタのポインタ」を要求する奴がいるのでその意味では言語仕様に必須ですが, そのような奴を除けば理論上「ポインタのポインタを使わなければ決してかけないプログラム」は存在しません.
もちろん「ポインタのポインタを必要とする奴」も, 言語仕様を変更すれば「ポインタのポインタ」を必要としないようにできますが.
ご回答ありがとうございます。
3次元の構造を持つなら 3次元配列が必要であり, それを動的に確保しようとしたら「ポインタのポインタのポインタ」は自然な発想だと思う.
というのは、私には難しすぎました。
実際にテストコードを書いて理解していこうと思います。
C99 の言語仕様上, そもそも「ポインタのポインタ」を使わないと決してプログラムが作れないということはない
というのは、なんとなくですが感覚でそんな気がします。
まだまだ理解が浅いです。
頑張って勉強したいと思います。
もしよろしければおすすめの書籍を教えてください。
No.2
- 回答日時:
3次元の構造を持つなら 3次元配列が必要であり, それを動的に確保しようとしたら「ポインタのポインタのポインタ」は自然な発想だと思う.
というのは現実的な話. C99 の言語仕様上は「そもそも『ポインタのポインタ』ですら必須ではない」とも言える.
No.1
- 回答日時:
「『ポインタへのポインタ』へのポインタ」が必要なとき
例えば
「ポインタへのポインタ」の参照渡し
「ポインタへのポインタ」の配列
「ポインタへのポインタ」のmalloc等による動的確保
無理矢理「意味付け」をしようとしていませんか?
いくつ*/&が付こうが、ポインタはポインタです。
>構造体がネストしていてそのメンバに文字列があって…
>となっている場合などでもダブルポインタ(ポインタのポインタ)で処理できるように思います。
この方が意味不明です。
struct A{
struct A * a;
char * s;
}
だとしても、 A.a->s は「構造体Aへのポインタa→その実体(構造体A)→そのメンバs(charへのポインタ)」であって「ポインタへのポインタ」にはなってないですし。
ご回答ありがとうございます。
私のポインタに対する理解が浅いんですね。。
ポインタ完全制覇とか、秘伝問答ポインタ編などは読了したのですが、
基礎的な仕組みがしっかり理解出来ていないから応用的なことも理解出来ていないのかと思いました。
ウチのチームが持っている開発部分は全体のごく一部で、外部から要求される仕様に対して、職場の諸先輩方は「*とか&つけて試行錯誤して動かしたい通りに動けばそれが正しい」というスタンスで、派遣社員の方がポインタについてかなり詳しいのです。
が、その派遣の方が切られてしまい、ポインタに対するチーム全体の理解がかなり浅いのが実情です。
ご指摘の、
「ポインタへのポインタ」の参照渡し、は関数に渡すときと理解しました。
「ポインタへのポインタ」の配列は、そういうものが必要になるときがあるのか…という印象です。
「ポインタへのポインタ」のmalloc等による動的確保については今の私ではちょっと理解できませんでした。
まだ理解が足りませんが頑張ってみたいと思います。
また、もしよろしければ何かおすすめの書籍を教えてください。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 配列とポインタについて 2 2022/06/02 11:53
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- デスクトップパソコン 全画面表示でもタスクバーを前面に隠す、表示させるようにしたい 3 2022/03/23 12:30
- その他(ブラウザ) Microsoft edgeのスクロールバーについて 2 2022/09/19 16:56
- デスクトップパソコン 急にWin10が通常画面にならない 3 2023/08/08 07:36
- C言語・C++・C# c言語 配列とポインタについて 3 2023/02/09 22:53
- C言語・C++・C# C言語で構造体の参照渡しができません 2 2022/12/18 21:22
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、写真のプログラムをどう直せ 2 2022/07/09 21:13
- C言語・C++・C# 双方向リスト 1 2023/06/28 04:16
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・「これはヤバかったな」という遅刻エピソード
- ・初めて自分の家と他人の家が違う、と意識した時
- ・いちばん失敗した人決定戦
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
Run-Time Check Failure #3とい...
-
CImage GetBitsメソッドについて
-
init関数の意味
-
【なぜポインタを使うのか】
-
[excel vba] マウスポインタの...
-
無効なポインタ操作のエラー
-
fopne で失敗する原因
-
参照型で受け取った引数をポイ...
-
関数にポインタを渡して動的確...
-
int型ポインタの加算
-
ExcelVBAでのkernel32(64bit)
-
NULLとブランクの違い
-
Voidポインタで受け取った変数...
-
デバイスハンドルとは?
-
#define NULL ((void *)0) の弊害
-
構造体の中の構造体
-
[C言語]単連結リストにおける着...
-
VB.NETで値や参照について ByR...
-
アプリを32bitから64bit移行
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
init関数の意味
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
Run-Time Check Failure #3とい...
-
ExcelVBAでのkernel32(64bit)
-
LPSTR型の初期化について
-
参照型で受け取った引数をポイ...
-
アプリを32bitから64bit移行
-
c言語で任意のファイルから読み...
-
関数ポインタの利点
-
コンストラクタでnewを失敗した...
-
C++で関数ポインタから関数名を...
-
ポインタについて
-
ハンドルはポインタか
-
基本アルゴリズムの『返す』の...
-
無効なポインタ操作のエラー
-
関数にポインタを渡して動的確...
-
[C言語] NULLは必ず0(番地)です...
おすすめ情報