Re: Pointer Type (Re: 構造体をポインタ...)
森山です。
On 27 Feb 2005 22:06:48 +0900
MAEDA Atusi <maeda-news@ialab.cs.tsukuba.ac.jp> wrote:
> > そうか〜、[↑]を使用しているのも有ったんだ...てっきり[ ^ ]だと
> > 見辛いので強調しているのかと思いました。[ @ ]を使用しているのは
> > 有りますね。しかし、[ ^ ]が無いマシンが有るとは知りませんでした。
>
> AlgolやPascalでは、「規格書や教科書で使う表記法」と「実際のコンピュー
> タへの入力で使う表記法」がありました。
>
> 教科書用の表記法では予約語は太字で表し、ポインタの表記に↑、かけ算の記
> 号に×などの記号を使い、またコメントは{ ... }を使っていました。
ああ、そうゆう事なのですね。
> なお、Pascalの後継であるModula-2やOberonでは、ポインタ型は
> pointer to integer
> とか、
> pointer to pointer to TreeNode
> のように書きます。
確かにこれだと分かりやすいですね。とは言え、私ごときがブツブツ
言っても始まりませんので、加藤さんや齊藤さんがおっしゃるように
思考を建設的な方向に向けてみました。
で、& と * を アッセンブラで言うところの Push Pop に見立て、
& : ポインタとしての階層を1段深める
* : ポインタとしての階層を1段浅くする
という風にとらえて、変数名には宣言時に [ * ]を使用した数だけ
接頭辞としての [ p ]を追加してみる事としました。又、宣言する時に
[ * ] は変数側では無く、型名側に着けるようにしてみました。
こうすれば、先のプログラムで呼び出し側の
biDone = biSetPointer ( &pgUser ) ;
の & は、ポインタとしての階層を1段深めるわけですから
この状態の変数は、 ppgUser と仮定出来るので、受けての関数
側で用意する変数の接頭辞は、ppgXXXX というようになる事がすぐに
判明します。この為、宣言するべき型名は tSample** となる事になる
ので、
int biSetPointer ( struct tSample** ppgTemp )
と、簡単に導き出せます。又 ppgTemp に pgSystem の ポインタを
設定するには、両者の階層を同じにする、つまり ppTemp の p を
取って pTemp にすれば良いので、ppgTemp に * を付けて *ppgTemp と
すれば * と 最初の p が相殺されて pgTemp となり、 pgSystem と
同等となりますから、
*ppgTemp = pgSystem ;
と成る事も、すぐに分かります。
この考えだと、例えば以下のように宣言した場合は
int* piDummy ;
piDummy : * も & も無くて接頭時の p が有るので、
データを指し示すアドレスとしてのポインタ。
*piDummy : * と p が 互いに相殺されるので iDummy 相当
となり、データとしての整数の値を示す。
&piDummy : & が有るので ppiDummy 相当となり ポインタの
有るアドレスを示す。
と考える事が出来るので、接頭時をうまく使用する事により、かなり
分かりやすくなるように思います。
で、最終的に例の動作確認用プログラムは以下のように
しました。
#include <stdio.h>
#define false 0
#define true 1
struct tSample {
int iDummy ;
int iDummy2 ;
} ;
static struct tSample gSystemArea ;
static struct tSample* pgSystem = & ( gSystemArea ) ;
int biSetPointer ( struct tSample** ppgTemp )
{
* ( ppgTemp ) = pgSystem ;
return ( true );
}
int main ( int srgc, char* argv[] )
{
static struct tSample* pgUser ;
int biDone ;
pgUser = ( struct tSample* ) malloc ( sizeof ( struct tSample ) ) ;
pgUser->iDummy = 15 ;
pgSystem->iDummy = 30 ;
pgUser->iDummy2 = 20 ;
pgSystem->iDummy2 = 40 ;
printf("pgUser->iDummy = %d\n" , pgUser->iDummy ) ;
printf("pgSystem->iDummy = %d\n" , pgSystem->iDummy ) ;
printf("pgUser->iDummy2 = %d\n" , pgUser->iDummy2 ) ;
printf("pgSystem->iDummy2 = %d\n" , pgSystem->iDummy2 ) ;
printf("pgUser = %d\n" , pgUser ) ;
printf("pgSystem = %d\n" , pgSystem ) ;
biDone = biSetPointer ( & ( pgUser ) ) ;
printf("pgUser->iDummy = %d\n" , pgUser->iDummy ) ;
printf("pgSystem->iDummy = %d\n" , pgSystem->iDummy ) ;
printf("pgUser->iDummy2 = %d\n" , pgUser->iDummy2 ) ;
printf("pgSystem->iDummy2 = %d\n" , pgSystem->iDummy2 ) ;
printf("pgUser = %d\n" , pgUser ) ;
printf("pgSystem = %d\n" , pgSystem ) ;
return ( 0 );
}
# ただこれだと、 宣言の int** は int&&の方がしっくりくるような...
まあ後は、ケースバイケースで、分かりやすい表記を考えてみたいと
思います。
--
K.Moriyama
Fnews-brouse 1.9(20180406) -- by Mizuno, MWE <mwe@ccsf.jp>
GnuPG Key ID = ECC8A735
GnuPG Key fingerprint = 9BE6 B9E9 55A5 A499 CD51 946E 9BDC 7870 ECC8 A735