【C言語】 ポインタ 配列 & 構造体 & 構造体配列

ポインタ   
ポインタ

  

コンピュータで数値や文字を扱う場合、変数を使うと言う話はしましたが、ではコンピュータのどの様に収納されているのでしょうか。

例えば、 
問題② 次の計算をしなさい。
  
80円のリンゴ5個と90円のリンゴ2個と60円の柿6個と70円の梨3個を買いました。

   と言う問題で

80円のリンゴ  5個
 
             (80円のリンゴ を x とおく )
x = 5        (変数 x 整数型 int型 に 5 を代入)
   
・・・ ここまでは 私たちが判る話 ここから先は コンピュータの話 ・・・
     
変数 x は int型で 4バイト 0x0250 ~ 0x0253 番地のメモリに 5 収納します。
   

     

メモリの話をしますと、全てのメモリには番号が振られています。
   
 番地それぞれに 16進数 で 00 ~ FF (2進数だと 0000 0000 ~ 1111 1111 )が入っています。
この値がコンピュータでは、プログラムや数値や文字になります。
   
             1番地 = 1バイト で割り付けられます
      

全ての変数には、置かれるメモリ上の位置(番地)があり、それをアドレスと呼びます。その変数のアドレスを表す型がポインタ型と呼ばれています。

   

アドレスの表し方
      
変数には、変数名、型、データ(文字、数値)、アドレスで構成されています。

    • int *b;
      ポインタの宣言
      変数のアドレス(番地)を収納する変数をポインタと言います。

    • b= a;
      &a は 変数a のアドレス になります。
      ポインタ  b に 変数a のアドレス を収納します。​
         

《 test038.c 》

#include<stdio.h>
int main(){
int a=5;
int *b;
printf ("① a=%x a=%d \n",&a,a ) ;
a=2;
printf ("② a=%x a=%d \n",&a,a ) ;
b=&a;
printf ("③ a=%x b=%x \n",&a,b ) ;
*b=100;
printf ("④ a=%x b=%d \n",&a,*b ) ;
a=*b;
printf ("⑤ a=%d b=%x \n",a,b ) ;
} 
結果

   
実行するたびに変数のアドレスは変わりますが、実行されている期間は変更されません。
  
    

ポインタ 配列

     
変数のポインタと同じように配列のポインタにもあります。配列の場合は最初の要素をポインタとしますが、配列の場合はポインタは変化します。
  
例えば、  
 ポインタ変数 P 
 まず、ポインタはA[0]になります。
 P = P+1;
 だと、1移動してポインタはA[1]になります。
 P = P+2;
 だと、2移動してポインタはA[3]になります。
  
   
 アドレスは int の場合、4ビットずつになります。
    A[0]   のアドレスは 0番地
  A[1]   のアドレスは 4番地  になります。
    
 

ポインタ と 配列
   
ポインタ変数 P とすると

    • P は A[i] の値が入ります。
       %x は アドレス値 
    • *P は 配列の要素になります。
        
《 test039.c 》

#include <stdio.h>
int main(){
int A[] = { 5, 10, 15, 20,25,30 };
int *P ,i;
P = A;
printf("%d %d \n", *P, A[0]);
printf("\n");
for(i=0;i<5;i++){
printf("%d %X %2d %2d \n",i,P,*P,*P+2);
P += 1;}
printf("\n");
printf("%d %X %2d %2d \n",i,P,*P,*P+2);
P =P - 5;
printf("\n");
printf("%d %X %2d %2d \n",i,P,*P,*P+2);
}
結果

8 ~ 10行 A[0] ~ A[4] の表示
10行     最後に 1 を加算されているので
12行     A[5] の表示になります。
13行     ポインタ値 に ー5 減算すると
15行     A[0] の表示になります。  
  
 

  
   
ポインタ 構造体 

変数、配列の要素ごとにポインタ(アドレス)がありますが、複数の型・変数から構成されている構造体は1つのポインタしかなく、構造体のメンバそれぞれには対応していません。

構造体のポインタ宣言
  
ポインタ宣言方法

    • struct list *p;
      struct 構造体テンプレート名 *ポインタ;
      ポインタの宣言
        
    • ポインタ扱い方
      (*p).no
      (*ポインタ).メンバ
        
      p->no
      ポインタ->メンバ
        -> アロー演算子:ポインタから構造体のメンバへアクセスするための演算子です。
        

《 test040.c 》

#include <stdio.h>
struct list {
int no;
int money;
char goods[10];
};
int main(){
struct list com001 = {1,80,"Apple"};
struct list *p;
p=&com001;
printf ("%d %d %s \n",com001.no, com001.money, com001.goods);
printf ("%d %d %s \n",(*p).no, (*p).money, (*p).goods);
printf ("%d %d %s \n",p->no, p->money, p->goods);
printf ("%x \n",p);
}
 
結果
   
     冒頭でも説明した通りアドレスは構造体に対応しています。

   

まとめ

 
C言語の最大の山場はポインタです。また、メモリの細かい管理もC言語の最大の特徴です。
配列のポインタの位置は移動します。要素の増減をした時、増減した値で留まる。配列は添え字の値を変える事で指定した値を得られる絶対値になりますが、ポインタは相対関係になります。

 

目次