今回は変数とメモリの関係について書こうと思う。
ちょっと「記号表」とかいろいろ難しいモノが登場するのだが、ちょっとわかりやすく説明するためにVBAを擬人化しておこうと思う。
コンパイラー君とインタープリターさんの紹介
まずあなたがVBAコードを書く。
すると、1行確定させるごとにコンパイラー君が間違ってないかチェックする。
もし間違いがあったらその都度あるいは実行前にコンパイラー君に注意される。
これがいわゆるコンパイルエラー。
問題なければ、コンパイラー君はPコードという中間コードを生成する。
Pコードは我々が目にすることはないが、VBAコードを圧縮して実行効率をアップさせたようなものだと思えば良い。
これを今度はVBAインタープリターさんが一行ずつ読んで順次実行していく。
もしエラーがあると途中で実行をやめてしまう。
これがいわゆる実行時エラー。
さて、まとめるとVBAのプログラムはこのような連携で動いているということになる。
ただし、コンパイラーが挟まると話がややこしくなるのでここでコンパイラー君とはお別れ。
以降はインタープリターさんが直接VBAコードを読むという設定で話を進める。
変数とメモリの関係
VBAで次のようなコードを書いたとする。
Dim a As Integer a = 10
単純な変数宣言と値の代入であるが、これを実行したとき、内部では何が起きてるんだろうか。
まずインタープリターさんがメモリーから2バイト確保する。
それからインタープリターさんは確保したメモリに初期値のゼロを格納し、変数名とアドレスの対応付けを「記号表」に書き込む。
この記号表というのもメモリ上のどこかにあるのだが、インタープリターさんが管理しているので我々プログラマーは普段意識することはない。
さて、次がa=10。このときインタープリターさんは記号表からaを探し、その番地を確認する。
そして、実際の番地に10を格納する。
そして次のように色々な型で宣言すると、
Sub hoge() Dim a As Integer a = 10 Dim b As Integer b = -200 Dim c As Integer c = 30 Dim d As Long d = 60000 Dim e As Double e = 12.5 End Sub
メモリと記号表はこんな感じになる。
ローカル変数の場合、スタックメモリという領域に保存されるのでメモリ番地は下から順に埋まっていくのが特徴である。
値渡し・参照渡しの意味をメモリの動作から考える
プロシージャ呼び出しの際にパラメーターを渡す場合、値渡しと参照渡しの二種類がある。
呼び出される側のプロシージャでByValキーワードを使えば値渡しとなり、何も書かないか、ByRefと書けば参照渡しになる。これもどういうことなのか図で説明しよう。
まずは値渡しのケース。
Sub プロシージャA() Dim a As Integer a = 10 Call プロシージャB(a) MsgBox a End Sub Sub プロシージャB(ByVal x As Integer) x = x * 2 End Sub
この場合は単純に10という数値がプロシージャBに渡る。
byValの場合、xのアドレスはaのアドレスとは別に用意されるので、当然プロシージャBでxの値を書き換えてもプロシージャAの変数aに影響はない。
さて、ここでプロシージャBをByRefに書き換えてみる。
Sub プロシージャB(ByRef x As Integer) x = x * 2 End Sub
すると今度は値が直接渡されるのではなく、変数aのアドレス「2880018」が渡される。
そしてxのアドレスが2880018となり、結果的にプロシージャAの変数aと同じアドレスを指すことになる。
さあ、そこでxを書き換えるということはつまり、変数aを書き換えてるのと同じってこと。
以上が値渡しと参照渡しの内部動作の違いである。
あとがき
今回はホントはオブジェクト変数とメモリの関係について書きたかったんだけれど、その前提として基本型変数でのメモリの動作を説明しておかないとなんのことかわからなくなるのでいろいろと書いてるうちに力尽きた。
オブジェクトの場合はまた今度にしよう。。
なお、厳密にいえば今回説明したメモリアドレスは実際は物理メモリアドレスではなく、OSによって管理されたプロセスごとの仮想メモリ空間のアドレスである。ツッコミがあるといけないので一応最後に補足しておいたが、これを語りだすとまた長くなるのでとりあえず便宜的にはメモリアドレスだと思ってもらって良い。
参考情報
Pコードについて
http://www.h3.dion.ne.jp/~sakatsu/Excel_Tips13.htm
https://support.microsoft.com/ja-jp/kb/209176
記号表について
明快入門 コンパイラ・インタプリタ開発 C処理系を作りながら学ぶ 林晴比古実用マスターシリーズ
- 作者: 林晴比古
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2015/03/27
- メディア: Kindle版
- この商品を含むブログを見る