プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌 前回までの復習 関数の宣言 複数のファイルからなるプログラム 複数のファイルからなるプログラムでのス コープ 標準ライブラリ関数とは何か 標準ライブラリ関数の使い方 今日学ぶこと メモリとアドレス ポインタ変数 アドレス演算子 &, 間接参照演算子 * ポインタを引数とすることで、呼び出し元の実 引数を変更できる constを仮引数に付けることで、実引数の変更 を抑制できる 教科書9.1から(p. 272~) アドレスって? 変数の値は、コンピュータの「メモリ」に記憶さ れる メモリには、16進表記で通し番号が振られて いる この通し番号を、アドレス(address)という 変数のアドレスを見る 変数が格納されているメモリのアドレスをしる には、アドレス演算子&を使う アドレス演算子の使い方 &変数名 例えば、aがint型の変数なら、そのアドレスは &a で知ることが出来る アドレスを端末に表示するには、%p 書式指 定子を使う(Sample1.cを打ち込んで、コンパ イル・実行してみよう) アドレスは、メモリ上の位置 アドレス演算子を使うと、変数aの値が、メモリ 上のどの位置に記憶されているか、が分かる Sample1.cで、さらにint型の変数b, cを追加し、 それらのアドレスも表示させてみよ。 気がつくことがあるか? ポインタ アドレスを格納する変数を、ポインタ型の変 数という ポインタ型の変数の事を、単にポインタという ことも多い ポインタ型の変数の使い方は、これまで学ん できた、他の型の変数と同じ ポインタの宣言 型名 *ポインタ変数名; ポインタ変数であることが分かるような名前を 付けることも多い 例: int *pA; int *Aptr; /* どちらもint型へのポインタ */ 変数名はあくまでpAとAptr Sample2.cを入力し、コンパイル・実行してみ よう ポインタ変数にアドレスを代入 Sample2.cの pA = &a; という行は、ポインタ変数pAに、int型の変数a のアドレスを代入している pAには、例えば0x22ef3c といった値が入る 「pAはaを指すポインタ」などという ポインタから変数の値を知る ポインタ変数の値(つまり、別の変数のアドレ ス)から、元の変数の値を知ることが出来る 間接参照演算子*をつかう *ポインタ変数名; 例:pAがint型の変数aのアドレスを格納した ポインタ変数なら、aの値は、 *pA /* これはint型 */ Sapmle3.cを入力し、コンパイル・実行してみ よう ポインタについて整理する a 変数a &a 変数aのアドレス 変数aのアドレスを格納したポインタ変 数 *pA 変数aのアドレスを格納したポインタ変 数が指している変数 == 変数a pA ポインタに別のアドレスを代入する ポインタ変数とは、アドレスを格納する変数 普通の変数と同じく、プログラムの途中で、ポ インタ変数の値を変更することが出来る ただし、int型を指すポインタ変数には、int型 の変数のアドレスしか格納できない Sample4.cを入力し、コンパイル・実行してみ よう 初期化されていないポインタ変数 ポインタ変数は、宣言しただけでは使えない 特定の変数のアドレスを代入し、初期化しな ければならない 初期化していないポインタ変数を使うと、ゴミ が表示されたり、実行時エラーになったりする (どのような挙動を示すかは、予言できない ポインタを使って変数を変更 Sample5.cを入力し、コンパイル・実行してみ よう pAがint型を指すポインタ変数の時、*pAはint 型.よって、*pA = 50; のように、代入できる この仕組みを使って、関数に引数を渡すと、 面白い応用がある 引数とポインタ int型の2つの値を交 換する関数void swap (int x, int y)を 書きたい →は思った通りには 動かない void swap (int x, int y) { int tmp; tmp = x; x = y; y = tmp; } なぜ前のswap()は動かないのか? Sample6.cを入力し、コンパイル・実行してみ よう→思ったように値が交換されない 関数の引数には、変数の値のコピーが渡さ れる これを、値渡し(pass by value)とか、値呼び (call by value)とかいう コピーを交換しても、元の変数には影響が及 ばない ポインタを使って解決 仮引数をポインタ変 void 数とする swap (int *pX, int *pY) { →参照 int tmp; Sample7.cを入力し、 tmp = *pX; コンパイル・実行して *pX = *pY; みよう *pX = tmp; } ポインタを使って解決(続) 前のスライドをswap()を使う。 引数として、&num1, &num2のように、変数の アドレスを渡す 仮引数は、&num1と&num2で初期化される pX = &num1; pY = &num2; *pX = num1; *pY = num2; これらが入れ替えられると、num1, num2その ものが入れ替えられる 参照渡し(pass by reference) 実引数を変更したくない場合 constという指定で、ポインタがさす実引数を 変更できなくなる void func (const int *pX); というプロトタイプ宣 言をみると、この関数はpXが指す変数を変 更しないことがわかる 同時に、func()を作成する際に、誤ってpXが 指す変数を変更してしまっても、コンパイラが その誤りを指摘してくれる 今日学んだこと メモリとアドレス ポインタ変数 アドレス演算子 &, 間接参照演算子 * ポインタを引数とすることで、呼び出し元の実 引数を変更できる constを仮引数に付けることで、実引数の変更 を抑制できる レポート課題 void mod (int *pA, int *pM) というプロトタイ プを持つ関数mod()は、*pAを (*pA) % (*pM)に置き換える.キーボードからint型の 値aとmを入力し、次のように出力するプログ ラムを作成せよ: ヒントは教科書p. 298の練習問題3. レポート課題(続) input a and m: 7 (ユーザの入力) 5 (ユーザの入力) 7 modulo 5 = 2 modulo 5. レポート課題(続) 締め切り:2004年11月8日一杯(日本時間で) 提出:メールで木村([email protected])まで. 感想などあると木村が喜びます
© Copyright 2024 ExpyDoc