計算機言語 I 第 13 回 動的なメモリの確保
この資料: http://www.math.u-ryukyu.ac.jp/~suga/gengo/2021/13.pdf
レポートへのツッコミ
2乗を計算するのにライブラリ関数pow()を使う人がいますが, 2乗くらいだと積を,つまりa2の計算を, a*aと書くのが普通です. 関数呼び出しは,幾らかの処理(前処理,後処理)をプログラムに要求しますが,a*a は,即座に計算できます. CPUが速くプログラムが小さいので, この講義でのプログラムでは気になりません が,大きなプログラム(例えば, Firefox のようなグラフィカルなWeb ブラウザや, 画像編集ソフト)では,こ のような細かいチリが積もって山となります. もちろん, 100乗を計算するときには,pow()を使います. 「臨 機応変」を意識してください.
分散の計算は, V(X) =E(X2)−E(X)2 を利用します(V(X)はX の分散,E(X) はX の平均). 分散の 定義式E((X−E(X))2)では,平均を計算した後で,再びデータを最初から読んで足し算しなければなりませ んが,E(X2)−E(X)2ではそれをする必要がありません.
動的なメモリ確保
今回の内容は割に難しいとされる事です. 少し,細かい話をします.
プログラムには, 実行時にならないとデータの大きさが決まらないことがよくあります.
例えば, この講義で使っているテキストエディタですが, どのくらいの大きさのファイルを編集するのかは, 実行するまでわかりませんし, 入力をどんどんしていくと必要なメモリもどんどん増えていきます. テキスト エディタの最初の回(情報科学演習)のときに述べましたが,入力画面に表示されている内容は, 一次記憶装置 の中に保存されており,その内容は実行しているプログラムが管理しています.
タイトルにある「動的なメモリの確保」とは,「実行中にプログラムが必要となったメモリをシステムに要 求してもらってくる」という動作の事です. 実用的なプログラムを作成しようとすると,このような仕組みが 必要であり,そのプログラムを記述するプログラミング環境も, このような仕組みが利用できるようにしてあ ります. 今回は, Cにおけるその仕組みの使い方です.
これまででは,「変数宣言」という形で, プログラム内では必要なメモリを確保してきました. しかし,これ までのメモリ確保の方法は,プログラム実行前に必要な変数の量が決まっているときだけです.
ポインタの復習
動的なメモリの確保では,ポインタを多用します. ポインタについてもう一度復習します.
Cのプログラムでは,一部の例外を除いて,識別子(名前,関数や変数の名前のこと)には,実行時に一次記憶 内でのアドレスが付与されることになっています. 実行時のある識別子のアドレスのことを,その識別子への
ポインタ(pointerは何かを指し示す物という意味の英語)と言います.
アドレス演算子&は,識別子に作用させることができ,その値は,その識別子を指すポインタになります. Cでは,ポインタ(アドレス)の値を保持するための変数型,「ポインタ型」を使うことができます. 例えば,
double *dp;
という宣言は, 次のように読みます. (下で「アクセス」と書いてある部分は, 代入や値を取り出すという意味 です.)
• dpはポインタ(アドレス)の値を保持するための変数であり,この識別子でアクセスできる値は,何らか のアドレスである. また,この宣言で定義されるのはdpという変数である.
• *dpという形でアクセスを行う際には, dpの値が指すの場所には, double型の値を保持するだけのメ モリがすでに確保されており,アクセスできる値は,その場所にあるdouble型の数値である. *dpとい う変数の宣言ではない.
上の事から, ポインタ型変数に対する * をdereference operater(意訳して間接参照演算子)と言ったりしま す. ポインタ値(アドレス値)を参照(refer)して,その場所にある値をアクセスするからです.
上の宣言では, dpには, アドレスとしての意味を持てば, (例えば符号無し整数値を)代入することができま す. 従って,プログラム的にアクセス出来ない場所の値をdpに代入しても,「文法エラー」にはならず,「実行 時エラー」になります. また, このようなプログラムでも,実行時エラーが発生しないこともあり, 「隠れたバ グ」がプログラムに残ることも,数多く発生しています. これは, OS開発用に作られたCの仕様(特徴)であ り,プログラマがその辺の責任を持つ必要があります.
2
これまでの事に関する補足
NULLポインタ. Null Pointer(ナルポインタ, ヌルポインタ)と呼ばれるもので, 「何も指していないという
ことが確定している」ポインタ値です. 大文字のNULL で参照されますが,ヘッダファイルに何がしか の値が,マクロ置換で与えられています. その値は, 処理系依存です.
式には値がある. プログラムでは,例えば,
a = b + c;
のようにして,色々な変数の値を変化させて行きます. 上のような物を「式(expression)」と言います. Cでは,式そのものが値を持ち,その値は左辺値です. 前回のプログラムで,
if ( ( fp = fopen("input.txt", "r")) == NULL)
という記述がありました. これは, 2番目のカッコ内の式( fp = fopen("input.data", "r"))が先 に実行されます. そして,この式の値がNULL か否かをチェックしているわけです.
変数のキャストに関する補足
教科書には,変数を別の型に変換するキャストの方法が書かれています.
このように,明示的に変数の型を変えるキャスト以外にも「暗黙のキャスト」があります. 例えば,異なる型 の変数の計算の際にこれは起きます.
double a = 1.0;
int b = 2;
double c;
c = a + b;
のようなプログラムです. 上のcの計算では,bの値がdouble型に変換されて,計算が実行されます. このよ うな時の暗黙のルールは,次です.
char < int < float < double
これは,異なる型の計算があったら,より右にある型にキャストして計算が実行されるという意味です. この講 義で使っている処理系では,int,floatがともに32bitなので,int型からfloat型へのキャストでは,情報 落ちが起き得ます. float型では,指数部を情報として持つため, 仮数部の有効桁数は23bitしかありません.
また, 皆さんが好きな,pow()というライブラリ関数も,本来の引数は double型ですが,int型を渡しても
double型に変換して,べき乗を計算してくれます. これは, ライブラリ関数がそのようにプログラムされてい
るのです.
malloc(), free() に関する補足
malloc()で確保したメモリ領域は,目的の型のポインタにキャストしないと, warning(警告)が出る処理系
が多いと思います. warning(警告)とエラー(error)の意味の違いに注意してください. warning は,「Cの文 法的には許容されるが,実行時エラーが起きる可能性がある.」というときに出されます. errorは文法上の間違 いで,コンパイラが処理できないということです. したがって, errorがあると,実行ファイルが作られません.
free()関数ですが, fclose()と似たようなことがあります.
プログラムが終了するときに, malloc() で確保されたメモリは,自動的にシステムに返されます. 従って,こ の講義で書くようなプログラムでは, free()を使わなくても問題になる事はありません. ただし,コンピュータ
の中には, networkサービスを実行するプログラムのように, 24時間365日動き続けることを想定しなければ
ならないプログラムもあります. このようなプログラムでは, malloc()で確保したメモリは,要らなくなった
らfree()でシステムに返却しないと,使える記憶域が無くなって,システム全体が停止してしまいます.
教科書, プログラム10.3で注目すべきは, malloc()で確保した連続したメモリは, 配列のようにアクセスで きることです.
ベクトルの添字の値をずらすのは,プログラマの慣れがあれば不要だと思いますので,プログラム10.4は飛 ばします.
4
ポインタへのポインタ
「ポインタ型変数」も識別子である. という認識は重要です. また「ポインタ型変数の配列」もCでは多く 現れます.
レポート問題 : 締め切り , 7 月 19 日 ( 月 ) 10:00 AM
今回は,適切なレポート問題を設定できなかったので,次をレポート問題にします.
前回の授業で, 41人分の成績を構造体 seiseki_tの配列に読み込むプログラムを書きました. この読み込 むプログラムに追加して,seiseki_tの配列を変数score の降順(大きい方から小さい方に並ぶよう)に並び 替えるプログラムを書け(つまり, 成績の良い順に配列を並び替える). 並び替えの方法は, 第6回の講義で解 説したバブルソートで良い. より効率的なアルゴリズムを知っていれば,それを利用しても良い. プログラム では,並び替えた結果を出力する部分も含める事.
件名: gengo2021-1 report 13.