3.3 整合配列、可変長配列

例えば2つの $ n$ 次正方行列 a, b の積を計算して、 その結果を c に代入する関数を考えてみよう。 Fortran の場合は次のようにすれば良い。
サブルーチン
      subroutine mulmat(c, a, b, ldim, n)
      integer ldim, n
      real*8 c(ldim,*), a(ldim,*), b(ldim,*)
      integer i,j,k
      real*8 s
      do i=1,n
        do j=1,n
          s=0.0
          do k=1,n
            s=s+a(i,k)*b(k,j)
          end do
          c(i,j)=s
        end do
      end do
サブルーチンを呼び出す側 (例えばメイン・プログラム)
      call mulmat(c, a, b, MAXM, n)
行列としての次数 $ n$ 以外に、 2次元配列の1番目の次元 (the leading dimension と呼ばれる -- だから ldim) MAXM をサブルーチンに渡す必要がある。 c(ldim,*) のように、 配列のサイズを引数 ldim を使って指定出来るのが 「整合配列」と呼ばれる機能である。

さて、それで C の場合であるが、C には Fortran のような整合配列の機能はない。 しかし C99 で導入された可変長配列の機能を使うとほぼ同じことが出来る。
関数
void mulmat(int n, int cols,
            double a[][cols], double b[][cols], double c[][cols])
{
  int i, j, k;
  double s;
  // 略 for (i=0; i<n; i++) for (j=0; j<n; j++) { s=0.0; for (k=0;...
}
関数を呼び出す側 (例えば main() から)
  mulmat(n, MAXN, a, b, c);
2次元配列の要素がメモリの中でどういう順番で配置されるか、 Fortran と C で違いがあるため (Fortran は column major, C は row major -- この辺も解説を書くべきか)、 サブルーチン・関数に渡すべき情報が、 a[MAXM][MAXN] のうちの MAXM, MAXNのどちらであるかに違いが出ている。


古い C では、可変長配列が使えなかったため、 個人的には 4 節で紹介するやり方を使い (M師匠に教わったんだっけ)、学生にも勧めていた。 そのうちに GCC で可変長配列が導入され、 C99 で規格化されたので、この項で説明したやり方が可能になったが、 C99 の次の規格 C11 では、可変長配列の機能はオプショナルとされたので、 このやり方を人に勧めて良いか、迷うところである (使っている人を見て、止めようとまでは思わない)。



Subsections
桂田 祐史
2017-03-06