計算機言語 I 第 9 回 ポインタ ( その 1)
この資料: http://www.math.u-ryukyu.ac.jp/~suga/gengo/2021/09.pdf
レポートへのツッコミ
とりあえず,私が書いたプログラムを例示しておきます.
unsigned long long fibonacci(int n) /* 繰り返し版 */
{
unsigned long long a=1;
unsigned long long b=1;
unsigned long long fib;
int i;
if (n==0||n==1) return 1;
for (i=2; i<=n; i++){
fib= a+b;
a=b;
b=fib;
}
return fib;
}
unsigned long long fibonacci(int n) /* 再帰版 */
{
if (n==0||n==1) return 1;
else
プログラムで用いる変数名ですが,プログラム内で重要な意味を持つ変数には, それに応じた名前を付けま す. (例えば,forループを回すため変数とかは,慣習上i などを利用しますが,これは,ループを回す以外に 使わないのと,慣習で読む人はわかってしまうからです.)
今回のレポートで, fibonacci 数列の値にfact という変数名を用いたかたがおられました. factは教科
書で階乗(factorial)の値だから,この変数名を用いているのです. 今後は,この辺りも注意してプログラムを
書いて下さい.
ポインタの解説への補足
ポインタや先週のレポート問題で処理時間に大きな差が出る理由を理解するには,コンピュータでの処理の 仕組み(のモデル)の概要を理解するのが早道だと思います.
ペンタブレットを利用してそれを解説しますので,中間モニタもしくはプロジェクタを見て下さい.
2
教科書 p. 102, プログラム 7.1
このプログラムは,複数回実行してみてください. 実行の度に出力結果が違うと思います.
ポインタ型変数
Cの解説をした本を読むときに注意すべきなのは,「ポインタ」という言葉の2重性だと思います.
• メモリ内の場所を示す意味でのポインタ
• 上の情報を保持するための変数であるポインタ型変数
Kernighan – Ritchieの本の記述が上の事を明確に書いていないために, それ以外の本もあまり明確な区別を
していないように見えます.
Cの特徴のひとつが,ポインタ変数を利用してハードウェアにかなり密着したプログラムを書くことができ ることです. これは Cの開発動機である,「OS を高級言語で記述する」ということからは当然の仕様なので すが,ハードウェアの知識がない人には,難しい言語仕様になってしまいます.
通常の高級言語では, ハードウェアに密着したプログラムを書くことはできないようになっています. それ は,そのようなプログラムはシステム全体に影響を与えることができ,最悪,間違ってシステムを止めてしまう プログラムや,意図しない動作を実行させる可能性があるからです.
Cが普及する以前は, ハードウェアに密着したプログラムは, アセンブリ言語(機械語)を直接書いていまし た. しかし,アセンブリ言語を書くのは大変で, Cが普及したためにそのようなプログラムは, Cで書かれるよ うになりました.
上で述べた「ハードウェアに密着したプログラムが書ける」ということは,セキュリティホールにも繋がり ます. 実際,その弱点をついたコンピュータウィルスが過去にたくさん作られています.
教科書 p.105, プログラム 7.3
このプログラムは, その前にある記述からすると誤植です. おそらく次のプログラムを掲載するつもりだっ たのでしょう. ただし,どちらの場合も実行時エラーになります.
#include <stdio.h>
int main() {
int *p=NULL;
*p = 10;
return 0;
}
Cの難しいところのひとつに, 上のような文法エラーは無いが実行時エラーが起きるプログラムが,簡単に 書けるところにあります. 通常の高級言語は,「文法的に正しいなら,実行時にはエラーにならない」を目指し て設計されます.
上の例は,教科書プログラム 7.3は, OSによって書き込みができない記憶場所にデータを保存しようとし て, OSからその動作を拒否されたわけです.
教科書p. 106,「重要ポイント」の(2)は誤解を与える表現です. 正確には,次のように書くべきです.
(2) (double *pという宣言があると)ポインタ変数pに代入されるアドレスには,double型を保持するの
に必要な記憶領域がすでに確保されていなければならない.
ポインタと配列
ポインタと配列との関係で重要なのは,次だと思います.
配列の先頭へのポインタは,配列名を参照することによって得られる.
ポインタの加法(減法)と配列要素との関係は, 教科書にある通りで,これも Cの特徴です. 配列の各要素を ポインタを利用しても参照することができるわけです. ただし, 今となってはこれはわかりづらさの原因にも なりますので,最近では,このような参照はあまり利用されません.
どうでも良い注意: 上のポインタと配列の関係ですが, C言語で見えるアドレスの差と, 実際のハードウェア でのアドレスの差は今では一致しません. 「仮想記憶,仮想機械」という技術を利用して,プログラマに,プロ グラム7.5のような実行結果で正しくプログラムが動くように見せています.
4
レポート問題
締切: 6月21日(月) 10:00(JST), 件名: gengo2021 report 9-1
char, double, long double, long longのそれぞれの型に対して要素数が 2個の配列を作り,先頭と次 の要素のアドレス値を出力するプログラムを書き,先頭と次の要素のアドレスの差は幾つになったかをレポー トせよ.
レポートは,プログラムとアドレスの差を両方記述すること.