こんなタイトルだと、
そもそも C に多次元配列はないとか、
関数に配列は渡せないなどと怒られそうだな。ごめんなさい。
サイズ指定のない2次元配列を渡せるようにする。
3次元以上も同じようにできると思う。多分。おそらく。きっと。
上手くいった例
2次元配列の各要素(配列)の先頭アドレスを格納した配列を用意し、
その配列の先頭アドレスを関数に渡している
もっと簡単な方法があるのかな。
#include <stdio.h>
void push(int **A);
int main(void){
int A[3][3];
int i,j;
int *B[3];
for (i=0;i<3;i++) B[i] = A[i];
push(B);
for (i=0;i<3;i++){
for (j=0;j<3;j++) printf("%d ",A[i][j]);
puts("");
}
return 0;
}
void push(int **A){
int i,j,k;
for (i=0,k=0;i<3;i++){
for (j=0;j<3;j++,k++) A[i][j] = k;
}
}
間違った例
次のコードはコンパイル時に警告が出て、実行すると Segmentation fault になる。
#include <stdio.h>
void push(int **A);
int main(void){
int A[3][3];
int i,j;
push(A); // 型が違う
for (i=0;i<3;i++){
for (j=0;j<3;j++) printf("%d ",A[i][j]);
puts("");
}
return 0;
}
void push(int **A){
int i,j,k;
for (i=0,k=0;i<3;i++){
for (j=0;j<3;j++,k++) A[i][j] = k;
}
}
警告: 互換性のないポインタ型から 1 番目の ‘push’ の引数に渡しています
備考: expected ‘int **’ but argument is of type ‘int (*)[3]’
追記 C++ の場合
多次元配列をラップするクラスを定義してその参照を関数に渡すっていう方法がありそう。
DoubleArray.h
class DoubleArray {
// N*M の配列
int N;
int M;
int *top; // 先頭の要素のポインタ
public:
DoubleArray(int *p,int n,int m);
int *operator[](int i);
int getN();
int getM();
};
DoubleArray.cpp
#include "DoubleArray.h"
DoubleArray::DoubleArray(int *p,int n,int m){
top = p;
N = n;
M = m;
}
int *DoubleArray::operator[](int i){ return top + M*i;}
int DoubleArray::getN(){ return N;}
int DoubleArray::getM(){ return M;}
main.cpp
#include <iostream>
#include "DoubleArray.h"
using namespace std;
void push(DoubleArray &D);
int main(){
int A[3][3];
DoubleArray D(&A[0][0],3,3); // ここがちょっとかっこわるい
push(D);
for (int i=0;i<D.getN();i++){
for (int j=0;j<D.getM();j++) cout << D[i][j] << ' ';
cout << endl;
}
return 0;
}
void push(DoubleArray &D){
for (int i=0,k=0;i<D.getN();i++){
for (int j=0;j<D.getM();j++,k++) D[i][j] = k;
}
}
追記(2)
プログラミング言語 C の新機能
にある可変長配列を使うことで解決した気がする。
こんなコードが許されるとは思わなんだ。
追記(3)
C++ では可変長配列がサポートされていないっぽい。。。 orz
C99では、可変長配列、複素数型の組み込み変数、指示初期化子、複合リテラルといった、
C++でサポートしていない数多くの新機能が追加された
可変長配列使おうとするとコンパイルエラーになった。