第7章 ポインタ

1 ポインタとは

教科書P80〜83

1-1 変数の物理イメージと論理イメージ

 例えば次のように変数を宣言した場合、論理イメージと物理イメージではそれぞれ次のようになる。

変数が宣言されたメモリ上の場所をアドレスといい、例えば変数aのアドレスは&aで求められる。

#include <stdio.h>

void main(void)
{
    int a = 10;
    printf("変数aの内容は%d アドレスは%d\n", a, &a);
}

※アドレスの値は実行環境により異なる(同じ値になるとは限らない)

1-2 ポインタ変数とは

ポインタ変数とは、アドレスを格納するための変数である。int型の変数のアドレスを格納するポインタ変数、char型の変数のアドレスを格納するポインタ変数など、変数の型の種類だけのポインタ変数がある。

[ポインタ変数の宣言方法]

int *pa;

「変数paは、int型変数のアドレスを格納するポインタ変数である」という意味になる。

[使い方]

  1. 変数のアドレスを知る
    int a = 10;
    printf("%d %d\n", a, &a);
    ※変数の前にをつけると、変数が割り当てられているメモリ上のアドレスという意味になる。
  2. アドレスを別の変数に格納する
    int a=10, *pa;
    pa = &a;
    printf("%d %d\n", &a, pa);
    ※ポインタ変数にはアドレスが格納されるため、ポインタ変数の中身を参照するとアドレスがそのまま表示される。
  3. アドレスが示す先に格納されているデータを参照する
    int a=10, *pa;
    pa = &a;
    printf("%d %d\n", a, *pa);
    ※ポインタ変数の前にをつけると、ポインタ変数内のアドレスが示す先の内容という意味になる。
  4. アドレスが示す先に格納されているデータを、別の変数に格納する
    int a=10, b, *pa;
    pa = &a;
    b = *pa;
    printf("%d %d\n", a, b);
    ※通常、b = a;とすると、変数aのデータが変数bに格納されるが、内部的にはこのように処理が行われている。

確認問題

教科書83ページ問7

2 ポインタと配列

教科書P86〜87

2-1 1次元配列(復習)

 C言語では、配列はメモリ上に連続して確保される

int ten[] = {100, 90, 65, 55, 80, 75, 70, 100, 80, 90, -1};

[使用例(ポインタなし)

int ten[] = {100, 90, 65, 55, 80, 75, 70, 100, 80, 90, -1};
printf("ten[%d] = %d\n", 0, ten[0]);
printf("ten[%d] = %d\n", 1, ten[1]);
[実行結果]
ten[0] = 100
ten[1] = 90

2-2 1次元配列をポインタに置き換える

 連続した領域に取られているということは、ポインタで参照することができる。

[使用例(ポインタあり)]

int ten[] = {100, 90, 65, 55, 80, 75, 70, 100, 80, 90, -1};
int *pten;
pten = ten;
printf("ten[%d] = %d\n", 0, *pten);
printf("ten[%d] = %d\n", 1, *(pten + 1));

[解説]

1. int *pten;
ポインタ変数ptenをint型で宣言
2. pten = ten;
int型配列の先頭アドレスをptenに代入する。
配列名tenは、&ten[0]と同じ意味になる
3. printfでの*pten
ptenに格納されているアドレス(int型配列tenの先頭アドレス)が示す先の内容
4. printfでの*(pten + 1)
ptenに格納されているアドレスに int型の長さを1つ分足したアドレスが示す先の内容

[アドレスの演算]

 ポインタ変数に格納された値(アドレス)に対して演算を行うことができる。例えばint型のポインタ変数に格納されている値に1を足すと、int型の長さ(2バイト)である2が加算される。
 この性質を利用し、配列内のデータをポインタで連続して参照することができる。

[使用例2(ポインタあり)]

int ten[10] = {100, 90, 65, 55, 80, 75, 70, 100, 80, 90};
int *pten;
pten = ten;
printf("ten[%d] = %d\n", 0, *pten);
pten++;
printf("ten[%d] = %d\n", 1, *pten);

[応用]

int ten[] = {100, 90, 65, 55, 80, 75, 70, 100, 80, 90, -1};
int *pten;
for (pten=ten ; *pten!=(-1) ; pten++)
  printf("%d\n", *pten);

[応用2]

int ten[] = {100, 90, 65, 55, 80, 75, 70, 100, 80, 90, -1};
int i, *pten;
pten = ten;
for (i=0 ; *(pten + i)!=(-1) ; i++)
  printf("%d\n", *(pten + i));

確認問題

教科書87ページ練習問題16(まずは例題16を理解すること)

3 ポインタと文字列

教科書P84〜85

3-1 文字配列(復習)

 C言語では、文字列を格納するデータ型は存在しないため、文字変数を配列にすることにより、1文字ずつ配列の変数に格納する。

char name[] = "Nagoya Kogakuin";

name[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15]
'N''a''g''o''y''a'' ''K''o''g''a''k''u''i''n''\0'
※文字列の最後にはヌル文字('\0')が入る
※文字配列宣言後に、文字列を代入することはできない

3-2 文字列をポインタで扱うには

例えば、文字列を縦に1文字ずつ表示するプログラムがある。

#include     <stdio.h>
void main(void)
{
    char str[] = "Kogakuin";
    int  i;

    /* 文字列データの表示 */
    printf("%s\n", str);

    /* 縦に表示 */
    for (i=0 ; str[i]!='\0' ; i++)
        printf("%c\n", str[i]);

}
<実行結果>
Kogakuin
K
o
g
a
k
u
i
n

このプログラムをポインタに置き換えると、次のようになる。

#include     <stdio.h>
void main(void)
{
    char str[] = "Kogakuin";
    char *pstr;

    /* 文字列データの表示 */
    printf("%s\n", str);

    /* 縦に表示 */
    for (pstr=str ; *pstr!='\0' ; pstr++)
        printf("%c\n", *pstr);

}

[解説]

char *pstr;
char型のポインタ変数pstrを宣言
pstr = str
ポインタ変数pstrに、文字配列strの先頭アドレスを格納
(pstr = &str[0] と同じ意味)
*pstr != '\0'
ポインタ変数pstrに格納されているアドレスが示す先の内容が'\0'以外のとき、 繰り返す
pstr++
ポインタ変数pstrに格納されているアドレスに、char型の長さを1つ分プラス
printf("%c\n", *pstr)
ポインタ変数pstrに格納されているアドレスが示す先の内容を出力

[応用]

#include     <stdio.h>
void main(void)
{
    char *pstr;
    *pstr = "Kogakuin";

    /* 文字列データの表示 */
    printf("%s\n", pstr);

    /* 縦に表示 */
    for ( ; *pstr!='\0' ; pstr++)
        printf("%c\n", *pstr);

}

確認問題

教科書85ページ練習問題15(まずは例題15を理解すること)

4 ポインタ配列

教科書P93〜94

4-1 ポインタ変数を配列で宣言する(文字列の場合)

 ポインタ変数も普通の変数と同様に、配列で宣言することができる。

char *pname[] = {"Candy", "Nancy", "Eluza"};

[解説]

char型のポインタ変数pnameは配列で宣言され、
pname[0]には"Candy"の先頭アドレスが、
pname[1]には"Nancy"の先頭アドレスが、
pname[2]には"Eluza"の先頭アドレスがそれぞれ格納される。

[プログラム例]

#include     <stdio.h>
void main(void)
{
    char *pname[] = {"Candy", "Nancy", "Eluza"};
    int i;

    for (i=0 ; i<3 ; i++)
        printf("%s\n", pname[i]);

}
<実行結果>
Candy
Nancy
Eluza

[例題] ポインタ配列で格納された文字列を1文字ずつ調べるには?

例えば上記プログラムを改造し、1文字ずつ縦に表示する。

#include     <stdio.h>
void main(void)
{
    char *pname[] = {"Candy", "Nancy", "Eluza"};
    int i;

    for (i=0 ; i<3 ; i++)
    {
        for ( ; *pname[i]!='\0' ; pname[i]++)
            printf("%c\n", *pname[i]);
    }

}
<実行結果>
C
a
n
d
y
N
a
n
c
y
E
l
u
z
a

[応用]

#include     <stdio.h>
void main(void)
{
    char *pname[] = {"Candy", "Nancy", "Eluza"};
    int i, j;

    for (i=0 ; i<3 ; i++)
    {
        for (j=0 ; pname[i][j]!='\0' ; j++)
            printf("%c\n", pname[i][j]);
    }

}
<実行結果>
C
a
n
d
y
N
a
n
c
y
E
l
u
z
a

確認問題

教科書94ページ練習問題19


[ TOP ]