Transcript 11_revised

第11週
ポインタ
プログラミング言語 2014
立命館大学情報理工学部
1
今回押さえる
プログラム
P.239 List10-9
入力された2つの整数値を
交換するプログラム
整数A:57
整数B:21
整数A:21
整数B:57
#include<stdio.h>
2
void swap(int *nx, int *ny)
{
int temp = *nx;
*nx = *ny;
*ny = temp;
}
int main(void)
{
int na, nb;
printf("整数A:");
printf("整数B:");
scanf("%d", &na);
scanf("%d", &nb);
swap(&na, &nb);
printf("整数A:");
printf("整数B:");
return 0;
}
scanf("%d", &na);
scanf("%d", &nb);
必須
今回押さえる
プログラム
 ポインタとアドレス
 区別できるように
 変数xに対し,
「x」「&x」
 ポインタ変数pに対し、
「p」,[&p」、「*p」
#include<stdio.h>
3
void swap(int *nx, int *ny)
{
int temp = *nx;
*nx = *ny;
*ny = temp;
}
int main(void)
{
int na, nb;
printf("整数A:");
printf("整数B:");
 ポインタと配列
scanf("%d", &na);
scanf("%d", &nb);
swap(&na, &nb);
printf("整数A:");
printf("整数B:");
return 0;
}
scanf("%d", &na);
scanf("%d", &nb);
なぜ上手くいかないか
void swap(int nx, int ny)
{
int temp = nx;
nx = ny;
ny = temp;
}
int main(void)
{
int na, nb;
printf("整数A:");
printf("整数B:");
scanf("%d", &na);
scanf("%d", &nb);
swap(na, nb);
printf("整数A:");
printf("整数B:");
return 0;
}
scanf("%d", &na);
scanf("%d", &nb);
4
p.226
実行結果と
その理由を考え
てみよう
5
必須
アドレス
p.227
メモリとは
 情報が入る箱が一列に並んだもの(途方もなく長い列)
アドレスとは
 各箱にふられた番号
 箱の番地に相当(だから,アドレス)
S
1091020
a
1091021
y
1091022
,
1091023
Y
e
s
1091024 1091025
1091026
\n
1091027
6
必須
ポインタ
p.227
変数:データを入れる箱
S
1091020
ポインタ:箱のアドレスを入れる箱
 アドレスも(数値だから)データ
 ポインタも変数の一種
 ポインタの変数にもアドレスがある
1091020
1091320
7
必須
アドレス演算子
p.228
ある変数のアドレスを求める
 アドレス演算子:「&」を使う
 例: int x; &xで変数xのアドレス
#include <stdio.h>
5
x
1091020 ← &x
変数nxのアドレスはコンパイラ
が勝手に決める
int main(void){
int nx;
int vc[3];
printf("nxのアドレス:%p¥n", &nx);
printf("v[0]のアドレス:%p¥n", &v[0]);
printf("v[1]のアドレス:%p¥n", &v[1]);
return 0;
}
アドレスをprintfで出力する時
は「%p」で指定
8
必須
ポインタ変数の定義
p.229
ポインタ変数:アドレスを保持する変数
int *p;
 POINT1:変数名の前に「*」を付ける
 POINT2:ポインタが保持するアドレスに格納される型を指定
 意味「int型の変数のアドレスを保持するポインタ」
double *q;
 意味「double型の変数のアドレスを保持するポインタ」
int型
x
5
1020
pはx
を指す
*p
1020
1321
double
型
y
4.23
1052
qはy
を指す
*q
1052
1315
9
必須
間接演算子
p.231
ポインタ変数が指す変数の参照や代入ができる
*p = 10;
y = *p;
 ポインタ変数に「*」を付ける
 pがxを指すとき、*pはxのエイリアス(別名)とも言う
*p
int型
x
*p
y
5
10
1020
10
1020
1321
1196
10
必須
例をみて考えてみよう
p.229
#include <stdio.h>
isako = &sanaka;
*hiroko = 180;
int main(void){
int sato = 178;
int sanaka = 175;
int hiraki = 165;
int masaki = 179;
int *isako, *hiroko;
printf("%d\n",
printf("%d\n",
printf("%d\n",
printf("%d\n",
printf("%d\n",
printf("%d\n",
isako = &sato;
hiroko = &masaki;
return 0;
}
printf("%d\n", *isako);
printf("%d\n", *hiroko);
sato);
sanaka);
hiraki);
masaki);
*isako);
*hiroko);
必須
#include<stdio.h>
ポインタと関数
入力された2つの整数値を
交換するプログラム
na
nb
5
8
1020
*nx
nx
1020
void swap(int *nx, int *ny)
{
int temp = *nx;
*nx = *ny;
*ny = temp;
}
int main(void)
{
int na, nb;
1150
*ny
11
ny
1150
ポインタが指す変数に対して
}
処理を行う
printf("整数A:"); scanf("%d", &na);
printf("整数B:"); scanf("%d", &nb);
swap(&na, &nb);
printf("整数A:"); scanf("%d", &na);
printf("整数B:"); scanf("%d", &nb);
return 0;
12
scanf関数とポインタ
p.236
scanfでは呼び出し側の関数が用意した変数に
値を代入する必要がある
→ 代入する変数のアドレスを引数で渡す
int main(void)
{
int na, nb;
printf("整数A:");
printf("整数B:");
return 0;
}
scanf("%d", &na);
scanf("%d", &nb);
13
必須
ポインタの型
p.238, 239
以下を実行するとどうなるか?
int main(void)
{
double dx = 2.5;
int *nx;
nx = &dx;
printf("dxの値:%.1f \n", *nx);
?
dx
return 0;
1020
}
ポインタは、
○○番地を先頭に格納された××型のオブジェクト
を指す
2.5
nx
1020
14
必須
ポインタと配列
p.240
#include <stdio.h>
v[0]=10, ptr[0]=10, *(ptr+0)=10
v[1]=20, ptr[1]=20, *(ptr+1)=20
v[2]=30, ptr[2]=30, *(ptr+2)=30
v[3]=40, ptr[3]=40, *(ptr+3)=40
v[4]=50, ptr[4]=50, *(ptr+4)=50
int main(void)
{
int i;
int vc[5] = {10, 20, 30, 40, 50};
int *ptr = &vc[0];
for(i = 0; i < 5; i++){
printf("vc[%d]=%d, ptr[%d]=%d", *(ptr+%d)=%d\n",
i, vc[i], i, ptr[i], i, *(ptr + i));
}
return 0;
}
15
必須
ポインタ演算
p.240, 241
ポインタの値(=アドレス)の加減乗算ができる
 ptrに1足すと、pが指す先の型のサイズ分値が増える
 ptr+iはptrが指すオブジェクトのi個後ろの要素を指す
 ptr-iはptrが指すオブジェクトのi個前の要素を指す
ptr[0] ptr[1] ptr[2] ptr[3] ptr[4]
*(ptr+i)は
ptr[i]とも書ける
*ptr
*(ptr
+1)
*(ptr
+2)
*(ptr
+3)
*(ptr
+4)
500
vc
[0] [1] [2] [3] [4]
500
502
504
506
508
ptr
16
配列の先頭要素へのポインタ
必須
p.242
 配列名vcと表記すると,配列vcの0番目の要素の先頭ア
ドレスを表す
int main(void)
{
int vc[3];
int *p = vc;
pの値:FFB0
vcの値:FFB0
vc[0]のアドレス:FFB0
vc[1]のアドレス:FFB2
printf("pの値:%p \n", p);
printf("vcの値:%p \n", vc);
printf("vc[0]のアドレス:%p \n", &vc[0]);
printf("vc[1]のアドレス:%p \n", &vc[1]);
return 0;
}
配列の受け渡し
#include <stdio.h>
void int_set(int
int_set(int vc[],
*vc, int
void
int no,
no, int
int val)
val)
{
int i;
for (i = 0; i < no; i++)
vc[i] = val;
}
int main(void)
{
int i;
int ary[] = {1, 2, 3, 4, 5};
17
必須
p.244, 245
配列vcを関数が受け取る
配列名aryはary[0]の
アドレスを表す
ポインタで受け取る
ことが可能
int_set(ary, 5, 0);
for (i = 0; i < 5; i++)
ポインタvcに対しても
printf("ary[%d] = %d \n", i, ary[i]); 配列のように扱える
return 0;
}
18
19
クイズ
2つの入力値を降順に並べるプログラム
どこが間違っているか
#include<stdio.h>
void swap(int *nx, int *ny)
{
int temp = *nx;
*nx = *ny;
*ny = temp;
}
void sort(int *n1, int *n2)
{
if(*n1 <= *n2)
swap(&n1, &n2);
}
int main(void)
{
int na, nb;
printf("整数A:");
printf("整数B:");
scanf("%d", &na);
scanf("%d", &nb);
sort(&na, &nb);
printf("整数A:");
printf("整数B:");
return 0;
}
scanf("%d", &na);
scanf("%d", &nb);
20
クイズの答え
n1, n2はポインタ変数であり、交換対象の変数
のアドレスが格納されている
#include<stdio.h>
void swap(int *nx, int *ny)
{
int temp = *nx;
*nx = *ny;
*ny = temp;
}
void sort(int *n1, int *n2)
{
if(*n1 <= *n2)
swap(n1, n2);
}
int main(void)
{
int na, nb;
printf("整数A:");
printf("整数B:");
scanf("%d", &na);
scanf("%d", &nb);
sort(&na, &nb);
printf("整数A:");
printf("整数B:");
return 0;
}
scanf("%d", &na);
scanf("%d", &nb);