見出し画像

C言語をしっかりと学びたい!(その1 変数の型)

今回のテーマ

char型もint型もfloat型もポインタ変数も全部同じ!

なにから書くのがいいのかと迷いましたが、やはり根本のところからやっていくのが自分的には一番な気がしているので、まず最初に書くべき内容はこれかなと

ただの0と1の羅列!

C言語はコンパイルされると最終的にはバイナリーファイルになります。つまり0と1の羅列になります。この0と1の羅列は基本的に16進数で言えば2桁、つまり1バイトで一つの意味を持ち、それをCPUが読み取ってその値に対応した処理を行います。そして、この数値と処理の対応のことを命令セットといいます。(多くのCPUではx86命令セットというものが使われています)

また、16進数2桁だと人間には分かりにくいので、数値と言葉を対応させたものがアセンブリ言語です。↓アセンブラでできること。

画像1​(http://www.jsk.t.u-tokyo.ac.jp/~ikuo/lec/soft3/instruction-sets.htmlより)

NOPは「何もしない」だそうですね!むちゃくちゃいろいろとやってくれてるけど(42tokyoの内輪の話)

例えば次のプログラムと同じようなことをしようとするとき

int i, j;
j = 3;
i = j + 2

コンピューター内部では以下のようなことが行われます。(実際にはプログラムカウンタとかが変わっていったりもするけど、今回はスキップ。いずれやりたいです。気になる人は「CPU レジスタ」とかで検索!)

①jのアドレスに3を代入する
②jのアドレスのメモリの値をレジスタ(CPU内のメモリ的な奴)にロードする
③その値に2を加算する
④その値をiのアドレスにストアする

僕が今回言いたいことは何かって言うと、CPU君はそんなに頭が良くないから、とにかく指定されたメモリからコピーしたりロードしてきたものの0と1を変えたりすることしかできない!と言うことです。

つまり、

int 型も char 型もポインタ変数も出て来ないんです!

CPU にとっては変数の型なんて興味の対象外で(そもそも型なんて概念はない)、ただ指定されたアドレスのメモリの値を、よく分からないまま言われたとおりに変えていくことしかしません。

つまり、本質的にはchar型もint型もポインタ型もどれも同じなんです。全て0と1の羅列を記憶するためのものです。(整数を表すものですと言ったこともありましたが、より正しくはこちらの表現だと思います)

ポインタ型はその整数が表すものが一般的にはメモリのアドレスですので(というよりメモリのアドレスを記憶するための型として作られたので)それを普通の整数として用いようとした場合はコンパイラーが文句を言うかもしれませんが、本質的には問題ありません。少なくともCPUは気にしません。

逆にポインタ変数にint型を代入しても、もちろんいいんです。例えば

int i = 42;
char *pc = (char *)i;

これも、コンパイラーが激怒すると思いますが、(もしかしたらErrorになるかもだけど、Warning程度でおさまるなら)問題ないです。

もしかしたらここで、

「i に 42を代入してるからいいかもしれないけど、-42 を代入していたら、アドレスは0以上しか存在しないんだからまずいだろ!」

と思ってしまう人もいるかもしれませんが、それはまだ

本質的にはchar型もint型もポインタ型もどれも同じなんです。全て0と1の羅列を記憶するためのものです。

これがしっかりと入っていないためです。int型での -42 というのは 

1111 1111 1111 1111 1111 1111 1101 0110 

のことです。これの一番左の1を他の位の1と同様に扱うのか、それとも符号として扱うのか、それはただの解釈の違いなので、int 型ではこれをマイナスとして解釈しますが、ポインタ変数では単純にむちゃくちゃでかい数値と解釈するだけです。

(念の為)CPUはその0と1の羅列を見て-42なりむちゃくちゃでかい数値なりと解釈しながら処理はしません。あくまでも0と1の羅列のまま処理します。

※浮動小数点型を扱うときの振る舞いは勉強不足で分かっていません。分かり次第おいおい書いていきます


-追記(2020/09/02 1:26)

浮動小数点はCPUではなくFPU(Floating Point Unit)という専用のところで処理されるらしいです。

まとめ

CPUはとにかく何も考えないでメモリ上の0と1をいろいろと変化させるだけしかしない。その0と1の羅列をどのようにして受け止め解釈するか、というのはこちら側の問題。


「アドレシングモード」を知ってる人への補足

int 型も char 型もポインタ変数も出て来ないんです!てとこで「アドレッシングモード」と思った人もいるかもしれませんが、あくまでもそれはCPUが動作するときにアセンブラの情報をメモってる的なことなのでここで言いたいことではないです。

実際、例えば7 × 6の結果を絶対アドレスとして使うのは別に問題ないですよね。


この記事が気に入ったらサポートをしてみませんか?