5/29(金)〜6/1(月) の学習ログです(主にC言語)

こんにちは。

いつもありがとうございます。

 

プログラミングを学び自分のアジェンダについて考えていたら、アートについての理解が進んだ安藤です。

アートの理解が進んだことで、自分の発想が拡張され、これからのライフワークにも関わってきそうでワクワクしています。

 

さて、今回も学習ログを残していきたいと思います。

 

 

 

2020.5.29(金) 

◎「中学生から始める983m式言語超入門」(Udemy)
セミコロン;は、「セパレータ」と言って、各値を分離するもの。

 

C言語(web記事「苦しんで覚えるC言語」)
●変数とメモリの関係
・配列の番号
実は配列名は、配列の最初の要素のアドレスを表していた。
各要素を参照する時に、[0],[1]と要素番号をつけるが、この意味は、
配列名のアドレス+要素番号のメモリを参照するという意味。
つまり、最初のアドレスを決めておけば、それに番号を足し算知りことで、
たくさんの変数が並んでいるという状態を表現することができる。

 

◎読書「まつもとゆきひろ コードの世界 スーパー・プログラマになる14の思考法」

 

◎読書「王様達ヴァインキング」

 

 

2020.5.30(土) 
C言語(web記事「苦しんで覚えるC言語」)
●ポインタ変数の仕組み
・ &つけが必要な変数の正体
「&」は変数のアドレスを求める演算子
演算子を使うと、その変数のメモリ上の番号を知ることができる。

・全ては値渡しである
値渡しとは、関数に単なる数値として情報を渡す方法。
変数を実引数に指定しても渡されるのは中身の数値。
変数の中身を関数の戻り値として渡される値に変更したい場合もあるので、
演算子を使って変数のアドレスを求めて、そのアドレスに戻り値の数値を渡す。
そうすれば、関数に呼び出し側のアドレス、即ちメモリ上の番号が伝わり、その番号のメモリの数値を書き換えれば、呼び出し側の変数の値も書き換えられるというわけ。
これが変数のアドレスを知る必要がある理由。

・scanf関数で&をつける理由
関数には変数に記憶された値のコピーしか渡すことができない。
これでは変数に新たな値を記憶させることはできない。
その場合も変数のアドレスを数値として渡してやれば関数側はそのアドレスにデータを渡すことができ、記憶することができる。
これが、scanf関数で変数に&をつける理由。

配列名には&をつけなくていいのは、配列名は配列の最初の要素がアドレス示しているから。なので配列名を渡すということはアドレスも一緒に渡していることになる。

◎読書「王様達ヴァインキング」

 

 

2020.5.31(日) 
C言語(web記事「苦しんで覚えるC言語」)
●アドレスを記憶する変数
・ポインタという単語
ポインタという呼び方は、総称であり、正確には3種類に分かれている。
①ポインタ型
int型やdouble型と同じような型。
②ポインタ値
アドレスのこと。
③ポインタ変数
ポインタ型で宣言されたポインタた値を記憶できる変数のこと。

・ポインタ型
ポインタ型とはアドレスを記憶する変数の型のことを意味している。
通常の型とは異なる特性がある。
それは、他の型から作り出される派生型であるということ。
例えば、int型の場合は独立した型。他の型とは何の関係もない。
けれどもポインタ型は、他の型とポインタ型を合体させて作る。

int型とポインタ型を合体させると、intへのポインタ型という型ができる。
double型の場合なら、doubleへのポインタ型が作られる。
また、intへのポインタ型に更にポインタ型を合体させて、intへのポインタのポインタ型という多重のポインタ型を作ることもある。

要するにポインタ型は、他の型と合体しなければ存在できない寄生虫のような型。

えー、ポインタ型はアドレスを記憶する変数の型。
アドレスは整数値に過ぎない。
では、なぜ整数値を記憶する型が他の型と合体する必要があるのか…。
その理由は、指定アドレスに記憶された数値を取り出すため。

例えば、int型、double型、char型は、全てサイズが違っている。
int型の場合、標準的なコンパイラでは4バイトのサイズ、億単位で存在するメモリというロッカーの4個分を使っていることになる。
int型の値を取り出すには、この4個をまとめて取り出さないといけない。

型によっては、メモリに記憶された2進数の読み方まで違ってくることもあるから、
元々の型が何だったかが分からない限り、記憶された数値を取り出せないわけ。

つまり、ポインタ型はどんな型の変数のアドレスだったか分かる必要がある。
そこで、予め他の変数と合体した形でポインタ型として作っておけば、そのポインタ型の変数に記憶された数値は、すぐに分かるというわけ。

・voidポインタ
単独に存在するポインタ型としてvoid型がある。
この型は、どんな変数のアドレスでも記憶することができるけど、元々の変数の型が分からないので、値を取り出すことはできない。

・ポインタ値
ポインタ値とは、ポインタ型の変数が記憶できる数値のこと、要するに、変数のアドレスの値のこと。

C言語の先祖であるB言語では、C言語のint型にあたる型にアドレスを記憶する仕組みだった。

C言語で、ポインタ値という数値で扱われている理由は、その目的の違いから。
通常の整数値は、プログラムの中で計算などを行うための数値。
ポインタ値は、計算に使う数値ではない。
なので、変数に記憶されている数値が、整数値なのか、ポインタ値なのかを区別しやすくするために、int型とポインタ型に分かれた。

・ポインタ変数
ポインタ型で宣言された実際の変数のこと。
この変数には、その元となった型の変数のアドレスを自由に代入できる。
更に記憶しているアドレスのメモリを読んだり書き換えたりすることができる。

他の変数とは性質が異なっている。他の変数はどんな値を記憶するにせよ、何らかの計算に使うことが目的だった。
文字型のcharですら、その実態は文字番号であり、どの文字を表しているのかを計算するための実数。
しかし、ポインタ変数では記憶しているアドレス値を計算に使うことはない。
ポインタ変数の役割は、それが示しているアドレス番号のメモリの値を計算すること。
ポインタ変数そのものを計算に使うのではなく、それが示している変数を計算するのが目的。

普段は、ポインタ変数として振舞っているんだけど、その変数の計算が必要になった時には、普通の変数に変身して計算に対応するというわけ。

この変身機能こそがポインタ変数の最大の特徴。
ポインタ変数は、ポインタ変数モードと通常変数モードの2つもモードを持っている。
必要に応じてそれぞれ切り替えて機能している。

 

 

 

2020.6.1(月) 
C言語(web記事「苦しんで覚えるC言語」)
●ポインタ変数の仕組み
・ポインタ変数の宣言
「*」はポインタ型を意味する。
変数の前に「*」がついていれば、ポインタ変数を宣言できる。

・アドレスを代入する
仮想メモリ
OSがメモリを管理して、多数のアプリケーションに適切にメモリを振り分けること。
多数のアプリケーションが同時に動く環境で、個々のアプリケーションが勝手気ままにメモリを使うと、別々のアプリケーションが使うメモリが重なってしまい正常に動作しなくなる。
そのため、OSが個々のアプリケーションが使うメモリが重ならないように管理している。

正常に管理されたアドレス番号を代入する確実な方法は、
もう1つ別の変数を宣言し、そのアドレスを代入する方法。
宣言された変数はOSによって管理されたメモリ領域に作られているため問題なく使うことができる。

・ヌルポインタ
ポインタ変数も宣言した直後はデタラメな値が代入されている。
その値が使用可能なアドレスかどうかは分からないので、そのアドレスを使うとバグになる。
これを防ぐにはアドレスを代入したか区別する必要がある。
そこでC言語には、ヌルポインタが用意されている。
NULLという記号をポインタ変数に代入しておけば使える状態でないことを示せる。
int *p = NULL;

int *p = 0;としてもヌルポインタが代入される。
これはC言語の文法として決まっていることであり、NULLが0であるということではない。
NULLは正しいアドレスが代入されていないことを示すための識別用の値であり、計算に使うための数値である0とは明確に区別されている。

 

 

今回はこれで以上です。

次回は金曜日に!

それではまた!