教科書P80〜83
例えば次のように変数を宣言した場合、論理イメージと物理イメージではそれぞれ次のようになる。
![]()
変数が宣言されたメモリ上の場所を
アドレスといい、例えば変数aのアドレスは&aで求められる。
#include <stdio.h> void main(void) { int a = 10; printf("変数aの内容は%d アドレスは%d\n", a,&a); }※アドレスの値は実行環境により異なる(同じ値になるとは限らない)
ポインタ変数とは、
アドレスを格納するための変数である。int型の変数のアドレスを格納するポインタ変数、char型の変数のアドレスを格納するポインタ変数など、変数の型の種類だけのポインタ変数がある。[ポインタ変数の宣言方法]
int *pa;「変数paは、int型変数のアドレスを格納するポインタ変数である」という意味になる。
[使い方]
- 変数のアドレスを知る
※変数の前に
int a = 10;
printf("%d %d\n", a,&a);&をつけると、変数が割り当てられているメモリ上のアドレスという意味になる。- アドレスを別の変数に格納する
※ポインタ変数にはアドレスが格納されるため、ポインタ変数の中身を参照するとアドレスがそのまま表示される。
int a=10, *pa;
pa = &a;
printf("%d %d\n", &a,pa);- アドレスが示す先に格納されているデータを参照する
※ポインタ変数の前に
int a=10, *pa;
pa = &a;
printf("%d %d\n", a,*pa);*をつけると、ポインタ変数内のアドレスが示す先の内容という意味になる。- アドレスが示す先に格納されているデータを、別の変数に格納する
※通常、b = a;とすると、変数aのデータが変数bに格納されるが、内部的にはこのように処理が行われている。
int a=10, b, *pa;
pa = &a;
b = *pa;
printf("%d %d\n", a, b);確認問題
教科書83ページ問7
教科書P86〜87
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
連続した領域に取られているということは、ポインタで参照することができる。
[使用例(ポインタあり)]
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を理解すること)
教科書P84〜85
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')が入る
※文字配列宣言後に、文字列を代入することはできない
例えば、文字列を縦に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); }
- 文字配列を用意しなくても、
文字列の先頭アドレスを 直接ポインタ変数に代入することができる。
(for文の1つ目の引数がないことに注意!!) char *pstr = "Kogakuin";
と、まとめて書くこともできる。確認問題
教科書85ページ練習問題15(まずは例題15を理解すること)
教科書P93〜94
ポインタ変数も普通の変数と同様に、配列で宣言することができる。
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
- char型のポインタ配列pnameにはそれぞれの文字列の先頭アドレスが格納されているため、printfの引数に直接アドレスを指定することにより、アドレスが示す先から始まる文字列を表示できる。
[例題] ポインタ配列で格納された文字列を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
- pname[0]
[0]は、pname[0]が示す文字列データの0文字目という意味になる。確認問題
教科書94ページ練習問題19