アカウント名:
パスワード:
俺の三重ポインタが火を噴く時が来たようだな……
#引き継いだソースにあってキレそうになった
良く"ポインタのポインタ"で混乱している人がいるけどtypedef 使えば理解もコーディングも楽になりますよ.
こんな感じです.
typedef int T;typedef T* PT; // "int" のポインタtypedef PT* PPT; // "intのポインタ" のポインタtypedef PPT* PPPT; // "intのポインタのポインタ" のポインタ
変数宣言時はこんな感じ
T t = 1; PT pt = &t; PPT ppt = &pt; PPPT pppt = &ppt;
関数の引数で3重ポインタ(?)を使う場合はこんな感じ.
void hogehoge( PPPT *pppt){ PPT ppt = ....; *pppt = &ppt;}
これなら,次に引継いだ人もキレないでしょう.
「P」を「*」と脳内変換しながら読まないといけない分だけ、よけいに分かりにくくなっています。
確かに意味がないですよね。どうせなら、
typedef int T;typedef T* PT; // "int" のポインタtypedef PT* ARR_PT; // "intのポインタ" の配列typedef ARR_PT* ARR_ARR_PT; // "intのポインタの配列" の配列
とやってもらった方が、配列の先頭のポインタなのか、要素のポインタなのかが判別しやすい。前者ならARR_ARR_PT、後者ならARR_PT*と宣言することで、一目瞭然。
多重ポインタって、指す先がポインタなのか(多次元)配列なのか、メモリ確保状況はどうなっているのかが管理しきれなくなってくるというのが混乱の元だと思います。そういう区別をtypedefを使ってうまく表現すれば、読みやすさに大きく貢献しますね。
Cのポインタの表記法そのものは(多重になっても)単純明快でややこしくないし、仮に*の数を間違ってもコンパイラが指摘してくれるから、あまり問題ではないと思います。
# 10重とか100重くらいになると*の並びを読むだけで目がくらむでしょうけど。# 数千重くらいになると画面全体が「*」で埋め尽くされて、画面をスクロールしても分からない# なんてことになりそう。# どういうところに10重とか100重とか数千重のポインタを使うと効果的なのか、見当もつかないけど。
そうそう。void sub( int *a) とかみたとき、配列として使うためにポインタになってるかアドレス渡しで値を取り出すためのポインタなのか、意図がわからないと判断つかない。
配列として使うのであればサイズを渡すべきとは思いますけどね。何度も修正した結果、当初の想定から外れて配列の範囲外アクセスとかありえますから。
サイズを渡せば疎結合になりますし。
Cの学習初期にポインタと配列が同じようなものだと覚えた人が、多次元配列とポインタの相性の悪さを受け入れられなくて挫折するみたいな感じじゃないでしょうか。
つ津
3重ポインタ使いはポインタの魔術師と呼ばれていた他に、マクロを多用するマクラーレンと呼ばれる奴もいた
魔術師なら「関数の配列へのポインタを返す関数へのポインタの配列へのポインタ」くらいは使ってみたりするのでしょうか。私には無理だけど。
いや、魔術師なら、自分自身と同じ型の関数へのポインタを返す関数をかけるはず。
宇宙論やってる人から見れば、8次元なんてまだまだ甘いです。
古いコードでは文字列の配列だけで二重(?)で、さらに可変長で…
何重のポインタを作ったところで、ややこしくなっていくのは確かですが、アイディアとしては同じだと思うのです。
可変重ポインタとかって、できないでしょうか。
void hogehoge(int n){double (*)na;::}
みたいな。実現方法も分からないし、実現したところで有効な使い方があるのかどうかも分からないけど。
上の議論とかもまとめてそうだけれど、型の検証がほしいから何重だろうがきちんと宣言するのであって、それが面倒だというなら void * にして、リファデリファの局面でキャストすればいいだけじゃん。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
人生unstable -- あるハッカー
関数の引数に (スコア:0)
俺の三重ポインタが火を噴く時が来たようだな……
#引き継いだソースにあってキレそうになった
Re:関数の引数に (スコア:2)
良く"ポインタのポインタ"で混乱している人がいるけど
typedef 使えば理解もコーディングも楽になりますよ.
こんな感じです.
typedef int T;
typedef T* PT; // "int" のポインタ
typedef PT* PPT; // "intのポインタ" のポインタ
typedef PPT* PPPT; // "intのポインタのポインタ" のポインタ
変数宣言時はこんな感じ
T t = 1;
PT pt = &t;
PPT ppt = &pt;
PPPT pppt = &ppt;
関数の引数で3重ポインタ(?)を使う場合はこんな感じ.
void hogehoge( PPPT *pppt)
{
PPT ppt = ....;
*pppt = &ppt;
}
これなら,次に引継いだ人もキレないでしょう.
Re: (スコア:0)
「P」を「*」と脳内変換しながら読まないといけない分だけ、よけいに分かりにくくなっています。
Re: (スコア:0)
確かに意味がないですよね。どうせなら、
とやってもらった方が、配列の先頭のポインタなのか、要素のポインタなのかが判別しやすい。前者ならARR_ARR_PT、後者ならARR_PT*と宣言することで、一目瞭然。
Re: (スコア:0)
多重ポインタって、指す先がポインタなのか(多次元)配列なのか、メモリ確保状況はどうなっているのかが
管理しきれなくなってくるというのが混乱の元だと思います。
そういう区別をtypedefを使ってうまく表現すれば、読みやすさに大きく貢献しますね。
Cのポインタの表記法そのものは(多重になっても)単純明快でややこしくないし、仮に*の数を間違っても
コンパイラが指摘してくれるから、あまり問題ではないと思います。
# 10重とか100重くらいになると*の並びを読むだけで目がくらむでしょうけど。
# 数千重くらいになると画面全体が「*」で埋め尽くされて、画面をスクロールしても分からない
# なんてことになりそう。
# どういうところに10重とか100重とか数千重のポインタを使うと効果的なのか、見当もつかないけど。
アドレス渡しのためなのか配列のためなのか? (スコア:0)
そうそう。
void sub( int *a) とかみたとき、
配列として使うためにポインタになってるか
アドレス渡しで値を取り出すためのポインタなのか、
意図がわからないと判断つかない。
Re: (スコア:0)
配列として使うのであればサイズを渡すべきとは思いますけどね。
何度も修正した結果、当初の想定から外れて
配列の範囲外アクセスとかありえますから。
サイズを渡せば疎結合になりますし。
Re: (スコア:0)
Cの学習初期にポインタと配列が同じようなものだと覚えた人が、
多次元配列とポインタの相性の悪さを受け入れられなくて挫折するみたいな感じじゃないでしょうか。
Re:関数の引数に (スコア:1)
つ津
Re:関数の引数に (スコア:1)
3重ポインタ使いはポインタの魔術師と呼ばれていた
他に、マクロを多用するマクラーレンと呼ばれる奴もいた
Re: (スコア:0)
魔術師なら「関数の配列へのポインタを返す関数へのポインタの配列へのポインタ」くらいは使ってみたりするのでしょうか。
私には無理だけど。
Re: (スコア:0)
いや、魔術師なら、自分自身と同じ型の関数へのポインタを返す関数をかけるはず。
Re:関数の引数に (スコア:1)
Re: (スコア:0)
宇宙論やってる人から見れば、8次元なんてまだまだ甘いです。
Re: (スコア:0)
古いコードでは文字列の配列だけで二重(?)で、さらに可変長で…
Re: (スコア:0)
何重のポインタを作ったところで、ややこしくなっていくのは確かですが、アイディアとしては同じだと思うのです。
可変重ポインタとかって、できないでしょうか。
void hogehoge(int n)
{
double (*)na;
:
:
}
みたいな。実現方法も分からないし、実現したところで有効な使い方があるのかどうかも分からないけど。
Re: (スコア:0)
上の議論とかもまとめてそうだけれど、型の検証がほしいから何重だろうがきちんと宣言するのであって、それが面倒だというなら void * にして、リファデリファの局面でキャストすればいいだけじゃん。