森山です。

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