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