ポインタにまつわる備忘録
C言語のポインタ表記は同じ記号を別の意味で使う事もあり
気を抜くとあっという間に混同してしまう。
さらに配列とポインタの扱いに互換性がある所も分かりにくい一因。
たまーにポインタを色んな表現で使い回しているプログラムもあるので要注意です。
特にややこしいところを備忘録としてまとめてみます。
基本のポインタと配列の宣言
int32 *i = &k //変数kのアドレスをiというポインタに代入する。
(kの型が何であろうとint32にキャストされる)
int32 i[ ] = &k //変数kのアドレスを i 配列の先頭アドレスとして代入する。
(型に関しては同上)
2重ポインタの宣言と定義。
int 32 **i = &k //ポインタ k のアドレスを2重ポインタのiに代入。
int32 *i[ ] = { &k , &j } //ポインタ行列の宣言と初期化。
i[0]に変数kのアドレスが代入される。
char *i[ ] = { "my" , "コン"} //文字列のポインタ配列。
i[0]に文字列"my"の先頭アドレスが代入される
ポインタの呼び出し方のバリエーション。( == は同義)
定義と呼び出しが同じ記号なので凄く紛らわしいですね。
① int32 *i = &k //この定義の場合は下記の等式が成り立つ
( kもint32の時)
*i == k
i[0] == k //配列で定義しなくてもこういう使い方が出来てしまう。
② int32 *i[ ] = { &k , &j }
i[0] == &k
*i [1] == j
② char *i[ ] = { "my" , "コン"}
i[0] == "my"の先頭アドレス
*i[1] == ' コ '
③ int 32 **i = &k // kはポインタ
i == &k
*i == k
**i == *k
関数のポインタ渡しのバリエーション。( == は同義)
ここら辺は凄くややこしい。
void Myprintf( char *p[ ] ); //プロトタイプ宣言
int main()
{
char *i[ ] = { "my" , "コン"} ;
Myprintf( i ); // i がポインタ配列の先頭アドレスを示す。
}
void Myprintf( char *p[ ] ) //void Myprintf( char **p) と宣言しても同じ結果。
{
printf(" %s \r\n %s \r\n " ,p[0] , p[1] ) //printfの文字列引数はアドレス。
出力は"my"と "コン"
printf(" %s \r\n %s \r\n " ,*p ,*(p+1) ) //出力は"my"と "コン"
}
ポインタ型関数と関数ポインタの宣言。
int32 *SwapByte(int16 k); //int32型のポインタを返すポインタ型関数
int32 (*GetMax)(int16 i) = GetMaxim; //上の関数構造を持つ関数ポインタの
宣言と定義
「GetMax」がポインタ名でGetMaxim関数の
先頭アドレスを代入
k = *GetMax( i ); という形で呼び出す。
int32 (*GetMax[ ])(int16 i) = { GetMaxim1 , GetMaxim2 }; //上の関数の構造を
持つポインタ配列。
GetMaxim1とGetMaxim2は既に宣言されている
必要がある
k = *GetMax[ 1 ]( i ); とすれば、
GetMaxim2関数が呼び出される。
書ききれませんでしたが、まだ構造体のポインタやポインタのキャストなどがあります。
ややこしいですか?俺もそう思います。
できればポインタ参照の*とポインタ宣言の*は別の記号にして欲しかった・・・・
これもポインタの柔軟性があるC言語ならではの表現ですね
頑張って慣れていければなーと思います。