Presentation is loading. Please wait.

Presentation is loading. Please wait.

基礎プログラミングおよび演習 第13回 担当:長谷川晶一5階522/520 14回は、期末テストをします。

Similar presentations


Presentation on theme: "基礎プログラミングおよび演習 第13回 担当:長谷川晶一5階522/520 14回は、期末テストをします。"— Presentation transcript:

1 基礎プログラミングおよび演習 第13回 担当:長谷川晶一5階522/520 14回は、期末テストをします。
期末テストは、この部屋で、Webや資料を見たり、 プログラム組んだりしながら回答していただきます。

2 ポインタとアドレス 112 2 int* p int a &変数名: 変数のアドレスを返す ポインタ:アドレスを入れるための変数
&変数名: 変数のアドレスを返す ポインタ:アドレスを入れるための変数 * ポインタ名:ポインタのアドレスにある変数 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 1 int a; int* p; a = 2; p = &a; printf(”p=%d\n”, p); printf(”*p=%d\n”, *p); int* p 112 int a 2 p=112 *p=2 実際のアドレスの値は、プログラムを 作ってみないと何になるかわかりません。

3 ポインタと変数 int* p; int a; ポインタ名 int* p; a = 2; int型の変数を指す型 p = &a;
printf(”p=%d\n”, p); printf(”*p=%d\n”, *p); ポインタ名 int型の変数を指す型 p = &a; 変数のアドレスを返す演算子 int型の変数を指すポインタ * p int型の変数を指すポインタ ポインタが指す変数を取り出す演算子

4 ポインタが指す変数への代入 p a 104 112 112 p a 104 112 112 10 p a 104 112 int a;
int* p; p = &a; *p = 10; 104 112 メモリ 112 p a 104 112 メモリ 112 10 p a 104 112 メモリ

5 ポインタと型 108 112 float* pf int* pi float f int a int a; float f;
int* pi=&a; float* pf=&f; *pi = 10 *pf = 2.4; *pi = *pf; pf = &a; pi = pf; 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 float* pf 1 108 pi=112 : aを指す pf=108 : fを指す aに10を代入 fに2.4を代入 a = fで、 aは2になる。 エラー: pfは、float型変数       しか指せない。 エラー: piとpf は型が違う int* pi 112 float f int a ポインタは、アドレスを入れる変数だが、 そのアドレスにある(はずの)変数の型が同じでないと代入できない。

6 課題20 変数のアドレスを見てみる について mainの変数はスタック領域 というところからとります。
課題20 変数のアドレスを見てみる について mainの変数はスタック領域 というところからとります。 たいていの処理系で、大きなアドレスから -向きに変数を取っていきます。 グローバル変数は、静的領域 というところからとります たいていの処理系で小さなアドレスから +向きに変数を取っていきます。 0x 0x 0x 0x 0x 0xBFFFF994 0xBFFFF995 0xBFFFF996 0xBFFFF997 0xBFFFF998 0xBFFFFFFE 0xBFFFFFFF 0xC 1 1 1 1 char gc short gs char gc; short gs; int main(){ char c; short s; } short s char c

7 引数にポインタを使う pはdを指す。 p ここで、*p = dを 書き換えている d pd 呼び出し元のdが 書き換わる
ポインタを渡すと、main()の変数を square()で書き換えられる。 →return を使わずに、関数から値を返せる。 pはdを指す。 p=pd; void square(double* p){ *p = *p * *p ; } p ここで、*p = dを 書き換えている int main(){ double d=2.0; double* pd = &d square(pd) ; printf(”%f\n”, d); } d pd 呼び出し元のdが 書き換わる 4

8 機能と構造 洗濯ばさみ (clothes-pin) 望遠鏡 (telescope) →名前は機能を表す。 関数の名前
機能:洗濯物を挟んで吊るすための物 構造:2つの棒がバネでつながっている。 望遠鏡 (telescope) 機能:遠くのものを見る 構造:筒に凸レンズと凹レンズが はまっている。  →名前は機能を表す。

9 良い名前とは? 関数の名前も、機能を表すのが良い。 関数の名前 関数の機能:ランダムな質点を返す
struct Mass randMass(){ struct Mass m; m.px = rand() % 60; m.py = rand() % 20; m.vx = 20; m.vy = 20; return m; } 関数の構造(動作): 構造体mを作って、 m.px に rand()が返した 値を60で割った値を代入し …

10 良いプログラム→よい関数 関数の名前 よい関数とは、どんな関数か
機能がわかりやすい → 名前は重要 わかりやすい名前がつけられるような機能に なるように、関数を設計する。 → mainの中から、名前がつけられそうな部分   を切り出して、関数にする。 名前をつけるときは、英単語を調べましょう。 構造がわかりやすい → あまり長すぎるのは良くない。    あまり短いと関数にする意味が無い。 数行~画面3枚分(90行くらい)が良い。

11 構造体のメンバーとポインタ ポインタは、構造体のメンバーも指せます。 m.px pm pd m. py m m. vx m. vy
struct Mass { double px; double py; double vx; double vy; }; int main(){ struct Mass m; struct Mass* pm; pm = &m; double* pd; pd = &m.vx; } m.px pm pd m. py m m. vx m. vy

12 ポインタをずらす pc pc+1 pc+2 ps ps+1 ps+2 ポインタと配列 ポインタに整数を足すと、足した分だけポインタがずれる。
配列は、メモリ上に詰まって並んでいるので、 ひとつずらすと次の要素のアドレスになる。 1 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x A 0x B 0x C 0x D cs[2] ’c’ cs[1] ’b’ cs[0] ’a’ ss[0] 0 ss[1] 1 pc pc+1 pc+2 ps ps+1 ps+2 ss[2] 2 char cs[3]; short ss[3]; int main(){ char* pc = &cs[0]; *pc = ’a’; *(pc+1) = ’b’; *(pc+2) = ’c’; short* ps = &ss[0]; *ps = 0; *(ps+1) = 1; *(ps+2) = 2; } char* なポインタは1byteずつ short*なポインタは2byteずつずれる (int*, float* は4byte, double* は8byte)

13 関数で配列を渡す 関数に配列を渡すことはできないが、 配列のアドレスを渡すことはできる。 ポインタと配列
// 文字列のコピー void strcpy(char* pdest, char* psrc){ int i; for(i=0;*(psrc+i); ++i){ *(pdest+i) = *(psrc+i); } *(pdest+i) = 0; int main(){ char src[7]=”string”; char dest[7]; char* psrc = &src[0]; char* pdest = &dest[0]; strcpy(pdest, psrc); printf(src); printf(”\n”); printf(dest); printf(”\n”); &src[0]と書くのが面倒なので、 src を &src[0] と同じ値と決めました。 なので、 char src[7]; char* p = src; // p = &src[0];と同じ とかけます。 ということは、 strcpy(&dest[0], &src[0]); の代わりに、 strcpy(dest, src); と書けます。 けれども、 配列が引数として渡されるのではないです。 配列の先頭のアドレスがポインタの引数に 渡されるだけです。

14 ポインタを配列っぽく使う 見た目と実態の違いに気をつけてください。 一見配列に見えますが、違うものです。 ポインタと配列
// 文字列のコピー void strcpy(char* pdest, char* psrc){ int i; for(i=0; psrc[i]; ++I){ pdesc[i] = psrc[i]; } pdesc[i] = 0; int main(){ char src[7]=”string”; char dest[7]; strcpy(dest, src); printf(src); printf(”\n”); printf(dest); printf(”\n”); 一見、src, descは配列に見えますが、 配列ではなく、ポインタです。 src[i]は *(src+i)と同じです。 *(src+i)と書くのが面倒なので、 src[i]と書いても良いことにしました。

15 文字列は文字の配列 ポインタと配列 msg[0] : ’s’ msg[1] : ’t’ msg[2] : ’r’ msg[3] : ’i’
msg[4] : ’n’ msg[5] : ’g’ msg[6] : 0 int main(){ char msg[] = ”string”; char * p = msg; p = ”abc”; printf(”Hello world!\n”); } p = &msg[0] p ’a’ ’b’ ’c’ ’H’ ’e’ ’l’ : 名前のない配列 (グローバル変数) int printf(char* pstr, …) 名前のない配列 (グローバル変数) よくわかんなければ、今はいいです。(これでやっと ”文字列“の説明ができました。)

16 ポインタと配列 課題21 文字列追加関数 文字列の後ろに文字列を追加する関数 void strcat(char* pdest, char* psrc); を作って、使ってみてください。 // 文字列を後ろにくっつける void strcat(char* pdest, char* psrc){ ここは考えてください。 } int main(){ char dest[20]="abcd"; strcat(dest, "efgh"); printf(dest); printf("\n"); char dest2[20]=" "; strcat(dest2, "ABCDEF"); printf(dest2); printf("\n"); 配列は、十分長く。 足りないと事故がおきます。 もし、char dest[5];だと はみ出してしまう。 ほかの変数や 最悪の場合 プログラムを 壊すことも dest[0] ’a’ dest[1] ’b’ dest[2] ’c’ dest[3] ’d’ dest[4] ’e’ dest[5] ’f’ dest[6] ’g’ dest[7] ’h’ dest[8] 0 こんな 変数は 無い abcdefgh ABCDEF

17 キャスト 型を変えることをキャストといいます。 ポインタをキャストすると変なことができます。 pd: 0x10 d p: 0x10
ポインタと配列 キャスト 型を変えることをキャストといいます。 ポインタをキャストすると変なことができます。 int main(){ int a; double d=10.4; a = (int)d; } (型) 変数 と書くと、変数を(型)に書いた 型にキャストできます。 普通に、a=10になります。 int main(){ double d = 0.2; double* pd = &d; int* p = (int*) pd; int a[2]; a[0] =*p; a[1] =*(p+1); printf(”%x %x\n”, a[0], a[1]) } pdを無理やり int* に変換 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 d pd: 0x10 p: 0x10 p+1: 0x14 doubleの中がどうなってるか見ることができる。

18 sizeof 演算子 変数のサイズを返す演算子です。 sizeof(char) = 1 sizeof(int) = 4
sizeof(double) = 8 sizeof d = 8 sizeof a = 20 sizeof a[0] = 2 length of a is 10 sizeof s = 8 変数のサイズを返す演算子です。 struct S{ char c; int i; }; int main(){ printf("sizeof(char) = %d\n", sizeof(char)); printf("sizeof(int) = %d\n", sizeof(int)); printf("sizeof(double) = %d\n", sizeof(double)); double d; printf("sizeof d = %d\n", sizeof d); short a[10]; printf("sizeof a = %d\n", sizeof a); printf("sizeof a[0] = %d\n", sizeof a[0]); printf("length of a is %d\n", sizeof a / sizeof a[0]); struct S s; printf("sizeof s = %d\n", sizeof s); s.c = 0x10; s.i = 0x ; char* p = (char*)&s; int i; for(i=0; i<sizeof(s); ++i){ printf(" %x", *(p+i)); } return 0;


Download ppt "基礎プログラミングおよび演習 第13回 担当:長谷川晶一5階522/520 14回は、期末テストをします。"

Similar presentations


Ads by Google