プログラミング演習Ⅱ 第10回 ポインタ(1) 情報・知能工学系 山本一公 [email protected] 前回の課題の解説・ポイント(1) • 課題8-1 – 例えば、文字列の長さは void rev_string(char str[]) { … int count = 0; while (str[count]) count++; … /* 文字列の長さを得る */ こんな感じで分かるので、 後はstr[i]とstr[count – i – 1]をひっくり返せば良い。 – 文字列の長さはstrlen()でも得られる 前回の課題の解説・ポイント(2) • 課題8-2 – 例えば、toupper()かtolower()を使って、 大文字か小文字に統一してから比較する int stricomp(const char str1[], const char str2[]) { int i = 0; while (str1[i] != 0 || str2[i] != 0) { if (toupper(str1[i]) != toupper(str2[i])) { return 0; } i++; } return 1; } 課題7の採点結果から(1) • 課題7-1 – 「関数型」なのだから、関数と同じように使 えないとダメ • 繰り返し使えないとダメ – ブロック化してないとダメ – 問題を変えない • もちろん変えたらダメに決まっています 課題7の採点結果から(2) • 課題7-2 – 行数をカウントする変数の初期化を忘れてい る 人が多かった 課題7の採点結果から(3) • 行の途中でEOFが来ることを考慮すると int ch, count = 0, cnum = 0; /* count:行数, cnum:処理している行の文字数 */ do { ch = getchar(); if (cnum == 0) /* 行頭だったら */ if (ch == EOF) break; else count++; if (ch == ‘\n’) cnum = 0; /* 改行で文字数を0に */ else cnum++; } while (ch != EOF); printf(“\nNumber of rows = %d\n”, count); 今日の内容 • 教科書 pp.225~237 • ポインタ • • • • • 計算機のメモリモデル アドレス演算子 ポインタ 間接演算子 ポインタと関数 計算機のメモリモデル • 変数の考え方 – 箱モデル ⇒ 独立の箱に変数の名前 (int) a (float) x floatなので、 4Byte分 – 実際の計算機のメモリ • 番地(アドレス)と変数名を対応させて記憶 0 a x 4 8 …… ☜ 番地 アドレス演算子 • 変数のアドレスを知りたい! – アドレス演算子 “&” • scanf()で使っていたアレ • 変数の”先頭番地”が値となる – “&a”は “4”、“&x”は“8”になる 0 a x 4 8 …… ☜ 番地 ポインタ(1) • アドレスを知ると何の役に立つのか? – 変数を介さずにアドレスから直接変数を 操作できる! – 配列や文字列の操作にとても便利 – 関数に副作用を起こさせるためにも便利 • 副作用:呼出し元の変数の値を書きかえる効果 • アドレスを格納する変数 ⇒ ポインタ型 – “*”を付けて宣言する int *ptr; ポインタ(2) • int型のオブジェクト – 整数(int型)の値を格納する • intへのポインタ型のオブジェクト – ≪整数を格納する箱≫の“アドレス”を 格納する int a, *ptra; ptra = &a; /* 変数 a のアドレスをポインタ変数 ptra に代入 */ 間接演算子(1) • ポインタ変数に格納されているアドレス にはどんな値が入っているか? – 間接演算子 “*” で値を取り出せる • 変数宣言と同じ “*” int a, b, *ptra; ptra = &a; /* 変数 a のアドレスをポインタ変数 ptra に代入 */ a = 100; b = *ptra; a = 200; b = *ptra; /* “*ptra”は“a”と同じなので b には 100 が入る! */ /* b には 200 が入る! */ 間接演算子(2) • 下の図のような場合 int *x, a, b; x = &a; /* 変数 a のアドレス(4)をポインタ変数 x に代入 */ a = 10; b = *x; /* “*x”は“a”と同じなので b には 10 が入る! */ *x x 4 a 10 b 10 …… 0 4 8 ☜ 番地 ポインタと関数(1) • C言語での関数の引数は“値渡し” – 関数の引数・変数は呼出し側の変数とは独立 ⇒ 呼出し側の変数の値は変更されない • “関数の独立性”という観点からは良いが、 値を変更したいときもある – ポインタを関数に渡して間接的に変更する! – 1つの関数から複数の値を返したい場合にも 使える ポインタと関数(2) • ポインタでアドレスを渡す void function(int *b) /* 引数に“*”を付ける */ { if (*b < 10) *b = 10; /* bが示すアドレスに 10 を格納 */ } int main(void) { int a; … function(&a); /* 関数に a のアドレスを渡す */ /* 関数から戻ってくると、aの値が変わっている */ … } ポインタと関数(3) • 下の図のような場合 – “&a”の値は“4” – 関数function()の引数“b” には“4”が渡される • アドレスが“値渡し”される – “*b”に代入すると、呼び出し元の“a”に 値が入る *b 0 a 10 b 4 …… 4 8 ☜ 番地 参照渡し • 変数の値ではなく変数の参照(変数の場所等、 諸々の属性)を渡すやり方 – C言語にはない。C++言語にはある。 – ポインタ渡しは、“ポインタの値渡し” • ただし – C言語におけるポインタ渡しを、 俗に“参照渡し”と呼んでいる – 本当の意味での“参照渡し”を指しているの か、 俗な言い方での“参照渡し”を指しているのか、 本を読んだりするときに気を付けること 今週の課題 1. main関数の中で、char 型変数 a, b[3]、 short型変 数 c, d[3]、 float型変数 e, f[3]、 double型変数 g, h[3]を定義し、それぞれのアドレス(配列は各 要素毎)を表示するプログラムを作成せよ。そ れぞれの変数がメモリ上でどのように配置され ているか、確認することがこの課題の目的であ る。 2. p.239、演習10-1のプログラムを作成せよ。 main関数等も作成して、完成したプログラムを 作成すること。 レポートについて • 電子メールで提出 – 提出先は [email protected] – Subjectを「プログラミング演習2 課題9提出 号・氏名 」とすること – C言語ソースファイルを添付する 学籍番 • メールの本文には何も書かなくて良いです – ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る – 提出締切は、1月16日(水) 12:00 (1週間後) 授業用Webサイト • URL: http://www.slp.cs.tut.ac.jp/~kyama/programming2/ – 課題のpdfファイルが置いてあります。 – 授業で使ったpptファイルを置いていきます。 • 質問メールは、以下のどちらかのアドレスまで – [email protected] – [email protected] • C-515へ直接質問しに来ても構いません
© Copyright 2024 ExpyDoc