ポインタを纏めてみた

1.ポインタとは
int *pointa→int型を指すポインタ(注意。間接参照演算子は変数pointaを指しているわけではない)
char *pointa→char型を指すポインタ(注意。間接参照演算子は変数pointaを指しているわけではない)
struct any *pointa→struct型を指すポインタ(注意。間接参照演算子は変数pointaを指しているわけではない)
一般に型Tの変数を指すポインタ型の変数pは T *pointaと定義する

  1. ポインタには型がある。そして、ポインタ型の変数もポインタ型の値もある。
  2. ポインタ型の値はメモリのアドレスである。
  3. ポインタ変数が基本型の変数のアドレス(定数)を保持しているとき、ポインタ変数は対象の基本型を指しているという。
  4. 基本型のアドレスの値を基本型の値という。
まとめ:
・変数に&(アドレス演算子)を適用すると、その変数のアドレスを取得することができる。このアドレスのことをその変数へのポインタという。
・ポインタ変数が別の基本型変数(一般的に)へのポインタを保持しているとき、ポインタ変数が基本型変数を指しているという。
・ポインタに間接参照演算子(*)を適用すると、そのポインタの指している先の値を表示することができる。また、ポインタに他の値を代入すると、指している変数の値を替えることができる。
気を付けるべき点:
ポインタとは、型はどうであれ、すべての基本型変数、派生型のポインタ変数、関数、構造体などその対象が持っているメモリー上の位置すなわち
アドレスの値(定数)のことを意味する。したがって、ポインタ型変数例えば、int *numとint numはそれぞれ別のポインタの値を持つことになる。
変数のポインタの値を調べるときは、printf("%p",&*num); printf("%p",&num);としてやればよい。ポインタ値は定数であって、ポインタ型変数以外に
その値を変えたり、代入したりすることなぞしてはいけない。ポインタ値を自在に扱って役割を果たすのは、ポインタ型変数のみである。

ポインタ演算:(pointa+sizeof(ポインタが示す型) * 増やす増分・減らす減分)
ポインタ型変数にn加算すると、ポインタはそのポインタが指す型のサイズ×nだけ前に進む。p++;
ポインタ型変数にn減算すると、ポインタはそのポインタが指す型のサイズ×nだけ後ろに進む。p--;

2.配列とポインタの密接な関係
配列名はその配列の先頭要素へのポインタ値と解釈される。
int array[10]は&array[0]と同じ型、同じ値となる。
つまり、array==&array[0]であり、恒等式は常に真である。
また、以上は同値 array[i]==*(array+i);

[  宣言時と数式との違い  ]
配列を宣言する時には、[ ]で要素数を指定し、
配列の要素を使う時は、[ ]で番号を指定するのですが、
実は、この2つも全く別の記号です。
宣言時の[ ]は要素数を指定するという意味を持ちますが、
数式の中で使用する[ ] は、アドレスに足し算する演算子です。
C言語では、似た使い方には同じ記号を使いたがる傾向があり、
その為、異なる意味に同じ記号を割り当てている部分が多いようです。
例:int array[5]={0,1,2,3,4};
     int i;                                                    
     int *pointa;
//arrayの各要素の値を表示       //arrayの各要素の値をポインタ型変数を使って表示する2例:                 pointa=&array[0];   
for(i=0;i<5;i++)                               for(pointa=&array[0]; pointa!=&array[5]; pointa++)                 for(i=0;i<5;i++)                     
         printf("%d",array[i]);                          printf("%d",*p);                                                          printf("%d\n",*(p+i));

pointa=&array[0];  ⇔pointa=array;
故に以下のコードが成り立つ
pointa=array; 
for(i=0;i<5;i++) 
printf("%d\n",*(pointa+i)); ⇔ printf("%d\n",pointa[i]); ⇔ printf("%d\n",array[i]);
つまり、
*(pointa+i)==pointa[i]==array[i]
式の中では、配列はその先頭要素へのポインタに読み替えられる。
3つ程の例外はあるが、後ろに添え字演算子[ ]が付くかは問題ではない。
pointa[i]は、*(pointa+i)の簡便記法である。
重要な補足:
配列の宣言時の添え字演算子と式の中のそれは違う。
上記の例はあくまでも、式の中での動きである。
また、宣言時の * と式の中での * も同様である。

関数に配列を渡すときは、配列名だけを引数として渡す。
配列を関数に渡すと、渡した先の関数の定義時に配列は、array[ ]から&array[0]にポインタに変換される。
したがって、呼び出し先の関数でポインタ型の変数を最初に定義してやると、いい。また、複数の戻り値を呼び出し元に返すことが出来るのが、
強い利点である。

//通常の配列名を渡すパターン                                                                      //ポインタとして渡すパターン
#include <stdio.h>                                                                                          #include<stdio.h>
#define GAKUSEISUU 5                                                                                #define GAKUSEISUU 5
double average(int array[ ]);                                                                             double average(int *pointa);
int main_jdjas(void)                                                                                          int main(void)
{                                                                                                                      {
      int array[GAKUSEISUU];                                                                           int array[GAKUSEISUU];
      int goukei=0;                                                                                              double heikin;
      int i;                                                                                                            int i;
     double heikin;     
                                                                                                                        puts("5人の点数を入力");
      puts("5人分の点数を入力");                                                 

     for(i=0;i<GAKUSEISUU;i++)                                                                       for(i=0;i<GAKUSEISUU;i++)
     {                                                                                                                   {
          scanf("%d",&array[i]);                                                                                            scanf("%d",&array[i]);
    }                                                                                                                     }                                                                                                             

     heikin=average(array);                                                                                     heikin=average(array);
     printf("平均=%.1lf 点",heikin);                                                                        printf(" 平均=%.1lf点",heikin);
}
double average_kkesg(int array[ ])                                                                           return 0;
{                                                                                                                         }
//int array[5];    
int goukei=0;                                                                                                        double average(int *pointa)
double heikin;                                                                                                      {
 int i;                                                                                                                      int goukei=0;
                                                                                                                             double heikin;
                                                                                                                              int i;
 for(i=0;i<GAKUSEISUU;i++)
 {                                                                                                                            for(i=0;i<GAKUSEISUU;i++)
      goukei+=array[i];                                                                                               {
 }                                                                                                                             goukei+=*(pointa+i);
 //heikin=(double)goukei/GAKUSEISUU;                                                                 }
return heikin;                                                                                                             return heikin;
}                                                                                                                              }   


2a.文字列リテラルとポインタ
文字列定数"string"は以下の文字型配列arrayと同値である。
char array[]={'g'.'o','o','d','\0'};
したがって、以下のように文字列型へのポインタCpointaを文字列定数で初期化できる。
char *Cpointa="good";

3.関数とポインタ
関数の引数に配列全体を渡すことはできない。ただし、配列の先頭要素のアドレスをポインタとして渡すことはできる。
関数に配列を渡すときは、配列名だけを引数として渡す。
配列を関数の引数として渡したければ、先頭要素へのポインタを渡す。
関数の引数にポインタがある場合、それはポインタとして扱われる。
以下のプロトタイプ宣言は同じ意味である。
int hoge(char array[ ]);==int hoge(char *array);



3a.関数ポインタ

4.構造体とポインタ
pointaが構造体へのポインタのとき、メンバを参照するには、
(*pointa).name;と表記し、ポインタpointaが指している構造体のメンバnameを参照している。
pointa->name; →上記の省略型( -> はアロー演算子)
注意→演算子の優先度から、( )を省略できない。*pointa.nameと書いたら、*(pointa.name)の意味になってしまう。 
構造体の実引数も関数に渡すときは、値渡しで関数に渡される。
注意事項として、構造体のメンバが多いときは、逐次その値がコピーして渡されるため、処理に時間がかかる。
故にポインタを使うことが望まれる。

//構造体を関数の引数として使う例                                                  //右の例をポインタで処理     
#include<stdio.h>

//構造体struct Carの宣言
typedef struct Car
{
      int plate_num;
     double gas;
}Car;

//show 関数の宣言                                                                                                    //構造体へのポインタを引数にもつ関数宣言   
void show(Car c); //構造体を引数にもつ関数                                                              void show(Car *pointa);

int main(void)
{
     Car car1={0,0.00};

     puts("ナンバープレートの番号は?");
     scanf("%d",&car1.plate_num);

     puts("残存ガソリン量は?");
     scanf("%lf",&car1.gas);
                                                                                                                              //構造体car1へのアドレスを渡す処理
     show(car1); //show関数を呼び出し、構造体 car1の値を渡している←ここがミソ               show(&car1);

return 0;
}

//show関数の定義
void show(Car c)
{
     printf("ナンバープレートの番号は%d:\t残存ガソリン量は%.1lf\n",c.plate_num,c.gas);
}

Nikkei225

28000-28550 up in the early session, down lately.