もう少し丁寧にc言語の入門記事を書いてみました6

記事
IT・テクノロジー
今回は構造体とポインタについて学びます。

最初の方でポインタとは変数のアドレスと
説明しましたが、いまいちピンとこなかった方も
いると思います。

主記憶装置であるメインメモリが
0x0000番地から0xFFFF番地まであるとして
それぞれの番地の事をアドレスといいます。
そして、それぞれの番地に値を代入していきます。

図で描くとこんな感じです。
memory.png
つまり、アドレスを取得さえすればその中身を書き換えたり
アドレスを加算すると配列のように使える事も出来ます。
#include<stdio.h>
int main()
{
    int num=5;
    int *po;
    po=&num;
    *po=3;
    printf("%d",num);
}
この結果は、3と表示されます。

ポインタの宣言は、型名 *ポインタの変数名です。
ポインタに変数のアドレスを渡す為には、
型名 *ポインタの変数名=&変数名;
か、
ポインタを宣言してから、
ポインタの変数名=&変数名とすればOKです。

ポインタから値を取り出すにはポインタの変数名の
先頭に*を付ければ良いので、
さきほどのソースで*po=3;とすると変数numまで
書き変わってしまう事になります。

ここで、ポインタに紐づけられた変数のアドレスを
書き換える方法を説明します。
#include<stdio.h>
int main()
{
    int num=50;
    int num2=32;
    int *po;
    po=&num;
    *po=3;
    printf("%p:%d\n",po,*po);
    po=&num2;
    printf("%p:%d\n",po,*po);
}
これは、ポインタ変数poのアドレスを&numから&num2に
書き換えたからポインタ変数poを*で取り出すと値が変わってしまいます。

あと、変数名はアドレスではないですが、配列名はポインタであることを
利用して、文字列の長さを求めてみましょう。
#include<stdio.h>
int len(char *s)
{
    int i=0;
    while(*s)
    {
        i++;
        s++;
    }
    return i;
}
int main()
{
    char str[100];
    scanf("%s",str);
    printf("文字列%sの長さは%dです。\n",
        str,len(str));
}
最初の入力バッファは固定長ですが、
サブルーチンlen()はポインタで文字列を計算しています。
というのも、scanfで%sで指定された変数strの文字列の末尾に
'\0'というNULL文字が必ず付いてきます。
なので、if文の条件やループの条件としては文字列の末尾は0と
見なされてループを抜ける事が出来る訳です。

こういう変数の末尾に特殊なデータを置いてループが何回されるか
分からない場合に備えた手法を番兵といいます。

例えば、●ンバーマンの爆風から避けるためにマップのあちこちに
置いたり、テトリスや将棋、オセロといったゲームにも壁として使います。

そして、変数aとbを交換するつもりの関数を用意しました。
#include<stdio.h>
void p(int a,int b)
{
    printf("Aは%d,Bは%dです。\n",a,b);
}
void swaptest(int a,int b)
{
    int tmp=a;
    a=b;
    b=tmp;
}
void swap(int *a,int *b)
{
    int tmp=*a;
    *a=*b;
    *b=tmp;
}
int main()
{
    int A=125;
    int B=37;
    swaptest(A,B);
    p(A,B);
    swap(&A,&B);
    p(A,B);
}
こうしてみると、swaptest()では、main関数に戻ってきても
値はポインタを使っていないため書き変わっていないのが分かります。
しかし、swapはポインタを使っているためmain関数に戻っても
変数Aと変数Bは交換されているのが分かります。

さて後半は、構造体です。
構造体が使えるとさらに高度なプログラムが書けるようになります。
頑張りましょう。

構造体は、複雑なデータのひとかたまりとして
使う場合が多いです。
例えば、FPSゲームでいうと自機や敵にHP、防御力、3次元座標、ジャンプ力、などいろいろなパラメータが想定されますが、
これがもしも、構造体無しで書かれたら、こんな感じのソースになります。
int PlayerHP=1000;
int PlayerDefencePower=100;
int PlayerX=50;
int PlayerY=0;
int PlayerZ=50;
int PlayerJumpPower=-10;
int EPlayerHP=1000;
int EPlayerDefencePower=100;
int EPlayerX=50;
int EPlayerY=0;
int EPlayerZ=50;
int EPlayerJumpPower=-10;


これでは、面倒な上にVisualC++のインテリセンスの機能が
使えません。
これを構造体ありで書き直すとこうなります。
typedef struct{
     double X,Y,Z;
}XYZ;
typedef struct{
     int HP;
     int DefencePower;
     XYZ xyz;
     double JumpPower;
}Player;
Player P;
Player Enemy[MAX_ENEMY];


サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す