LoginSignup
2
1

More than 5 years have passed since last update.

多次元配列を多重Forで走査する場合の囲む順番の注意

Last updated at Posted at 2016-12-01

はじめに

自分がいつも行っている囲み方が、(体感できるかは置いておいて)効率面であまりよろしくない方法だった。

自分の感覚だと違和感があったので、同じ感覚の人もいるだろうと備忘録ついでに公開。

配列について

同じ種類のデータをメモリ上に隙間なく並べたもの。
使うデータが隣り合っているなら、CPUがデータを求めてメモリ上を探す手間が減るため処理効率が良くなる。

→メモリのアドレス順に配列の要素にアクセスすると効率が良い。

具体的には→大きい次元の添え字から囲む

悪い例

'悪い例
'sampleArray(0 To X, 0 To Y)
Dim i&, j&
For i = 0 To X  '1次元目
    For j = 0 To Y  '2次元目
        '
        'Debug.Print VarPtr(sampleArray(i, j))
        'sampleArray(i, j)を使って何か処理
        '
    Next j
Next i

良い例

'良い例
'sampleArray(0 To X, 0 To Y)
Dim i&, j&
For j = 0 To Y  '2次元目
    For i = 0 To X  '1次元目
        '
        'Debug.Print VarPtr(sampleArray(i, j))
        'sampleArray(i, j)を使って何か処理
        '
    Next i
Next j

i,jの順番がずれるのが気になるが、こちらのほうがメモリのアクセス順の面でより良い方法となる。

その他サンプル

'Excelで実行すること前提
Sub 配列アドレステスト()
    Dim tmpArray() As Variant

    Let tmpArray = Range("A1:A9").Value
    Call PrintArrayAddress(tmpArray, "9行1列")

    Let tmpArray = Range("A1:I1").Value
    Call PrintArrayAddress(tmpArray, "1行9列")

    Let tmpArray = Range("A1:C3").Value
    Call PrintArrayAddress(tmpArray, "3行3列")

End Sub

Sub PrintArrayAddress(ByRef inputArray() As Variant, ByVal iArrayName As String)
    Dim i&, j&
    Debug.Print vbCrLf; iArrayName; "の配列アドレス"

    '良くないアクセス方法なので3行3列の配列ではアドレスがずれて出力される
    For i = LBound(inputArray, 1) To UBound(inputArray, 1) Step 1
        For j = LBound(inputArray, 2) To UBound(inputArray, 2) Step 1
            Debug.Print iArrayName; "("; i; ","; j; ")", VarPtr(inputArray(i, j))
        Next j
    Next i
End Sub

参考

いつもお世話になっています。

VBA ReDimはなぜ最後の次元だけしか拡張できないのか。

VBA 配列とコレクションの違いをメモリ上のデータ構造から理解する

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1