ポインタを引数として使う
前回はアドレスと配列について解説しました(前回の記事)。配列は先頭アドレスのことでコードの表現は違ってもポインタ変数と同じです。今回はポインタ変数を関数の引数として使う方法について記載します。簡単にいうと関数の引数にアドレスを放り込みます。以下CとVBAのサンプルコードを記載します。
#include <stdio.h>
const int MAX=100; //配列最大値
void pTest(int *p)
{
for(int i=0;i<MAX;i++)
p[i]=i+1;
}
int main()
{
int arr[MAX];
pTest(arr); //配列の先頭アドレスを渡す
for(int i=0;i<MAX;i++)
printf("arr[%d]=%d\n",i,arr[i]);
return 0;
}
'VBA
Option Explicit
Const MAX As Integer = 99
Sub pTest(ByRef p)
Dim i As Integer
For i = 0 To MAX
p(i) = i + 1
Next i
End Sub
Sub main()
Dim arr(MAX) As Integer
Dim i As Integer
Call pTest(arr)
For i = 0 To MAX
Debug.Print ("arr(" + CStr(i) + ")" + CStr(arr(i)))
Next i
End Sub
C言語はポインタ変数の宣言と同じで引数でも*をつけて宣言します。対してVBAの引数は変数名の前にByRefを加えます。ByRefはby referenceの略で「参照で」という感じの意味になります。サンプルコードを動かしてみると前に変数の有効範囲について記載しましたが、グローバル変数以外で他の関数で宣言した変数はその関数内または(C言語の場合は{}内)でしか使えませんでしたが、アドレスを引数として使うことで外部の関数からもアクセスできるようになります。結果サンプルコードのmain関数で宣言したarrの数値が外部関数によって値が代入されています。先程グローバル変数以外と言いましましたが、もちろんグローバル変数を使えばポインタの引数は使わずに以下の様なシンプルなコードが書けます。
グローバル変数を使った場合
#include <stdio.h>
const int MAX=100; //配列最大値
int arr[MAX];
int main()
{
for(int i=0;i<MAX;i++)
{
arr[i]=i+1;
printf("arr[%d]=%d\n",i,arr[i]);
}
return 0;
}
'VBA
Option Explicit
Const MAX As Integer = 99
Dim arr(MAX) As Integer
Sub main()
Dim i As Integer
For i = 0 To MAX
arr(i) = i + 1
Debug.Print ("arr(" + CStr(i) + ")" + CStr(arr(i)))
Next i
End Sub
結果が同じとなる2つのコードの違いはグローバル変数arrは常にメモリを使用している点で、関数内で宣言されたarrは関数の処理が終わるとメモリが解放されます。常にメモリを確保しているグローバル変数に対して、関数内で変数を宣言したプログラムの方が関数が動いていない時のメモリ使用量は小さくなります。とは言うものの、今のコンピュータはメモリの容量がかなり大きいのでそんなに心配しなくても大丈夫です。メモリ不足が発生しそうな大規模なソフト開発や、メモリの少ないマイコンを使う場合にポインタは一つの武器だという事を認識できていれば充分だと思います。
次回は構造体について解説します。