2017-02-07 130 views
1

多次元配列を関数に渡すコードを理解しようとしています。しかし、この関数のプロトタイプは興味をそそられています。配列の奇妙なパラメータ回復

プログラムでは、この「タブ」変数を作成:

#define N 8 

float tab[N][N]; 
tab[0][0] = 2; tab[0][1] = 3; tab[0][2] = -1; 
tab[1][0] = 3; tab[1][1] = 1; tab[1][2] = -4; 
tab[2][0] = 1; tab[2][1] = 2; tab[2][2] = 3; 
hello(tab); 

をそして、我々はこの機能を持っている:

function hello(float mat[][N]) { 

私はいけないハロー機能は[]空とタブの変数を取得する理由を理解し、それから[N]で。それは何が変わるのですか?私は理解していない... [] []タブをしないのはなぜですか?

コードは良い開発者によって作成されたと思われるので、N変数は何も理由がないとは思わない。

私にこのことを説明できる場合は、お時間をいただきありがとうございます!

The original code

+2

答えの約半分がここにあります:http://stackoverflow.com/questions/1461432/what-is-array-decaying。それから、後半を推論することができます。配列が減衰すると、最初の次元のサイズが失われます。 – user4581301

+1

コメントを書き直す必要があります。サイズは必ずしも失われません。それは捨てられるかもしれません。 'float mat [] [N]'は、破棄することを選択し、長さ 'N 'の未知数の配列へのポインタになります – user4581301

+0

@ user4581301あなたの答えをありがとう。あなたが私に提供したstackoverflowの答えは、私が理解するために少し高レベルです。 I配列の最初の次元には、2番目の次元の各coloneの開始点のアドレスが含まれていましたが、私の最初の次元の大きさが緩んでいたら、配列から出てsegfaultingすることなく、どうすれば安全に私の第二の次元に到達できますか? – Doctor

答えて

1
float tab[N][N]; 

は、Nの配列をNで定義します。配列がメモリにどのように表現されているかに関係なく、プログラムロジックをどのように指向しているかは、行または列を使用することはありません。ちょうどそれがmat[0..N-1][0..N-1]でアクセスできるN * Nのメモリのブロックであることを知っている。サイズは既知で一定です。配列を定義するときは、配列のサイズを知っていなければならず、このサイズは変更できません。あなたはサイズがわからない場合は、配列のサイズが不明であるため、std::vectorまたはstd::vector<std::vector<YOUR TYPE HERE>>

float tab[][]; 

を使用することは違法です。コンパイラは、どのくらいの記憶域を配列に割り当てるべきか、また機能している(たとえ欠陥があっても)プログラムを生成することができないというヒントを持っていません。

このような

function hello(float mat[][N]) 

として関数に配列を渡す場合、配列はポインタに減衰します。詳細:What is array decaying?アレイが減衰した後、最初の次元のサイズは失われます。配列を安全に使用するには、配列のサイズをすでに知っているか、別のパラメータとして提供する必要があります。例:

function hello(float mat[][N], size_t matLen) 

問題のサイズはNです。あなたはそれがNだ知っている、あなたは安全に任意のサイズを提供し、単に境界としての機能内Nを使用せずに

hello(mat); 

を呼び出すことができます。 Nは独占的ではないmagic numberですが、よりわかりやすい名前を付けることができます。

また、完全に明示的および

function hello(float mat[N][N]) 

と時々、それはトレードオフの価値が作っているN.により、サイズMの配列との機能を使用できるとともに、任意の曖昧さを取り除くことができます。

+0

このパラメータの宣言float * mat [N]は、float mat [] [N]、 –

+0

@ VladfromMoscowと同値ではありません。そうではありません。私は何か完全に間違ったことをした。 – user4581301

+0

あなたの答えをありがとう。わかった。コンパイラが動作するための最小限の表記法! – Doctor

0

「untechnically」私は少し説明しましょう、おそらく包括:

は、2次元の「ROW」は、行の略floatの配列、および「COL」としてfloat tab[ROW][COL]を考えます列の略で、配列は、他の次のメモリ1行全体にマッピングされていると思い、ROW=3COL=3ためすなわち

r0c0,r0c1,r0c2 
r1c0,r1c1,r1c2 
r2c0,r2c1,r2c2 

。コンパイラがtab[2][1]を書き込む場所を見つけなければならない場合は、行のサイズの2倍+ 1(行サイズは実際には列の数であるCOL)を取る必要があります。したがって、セルのアドレス指定には行のサイズを知ることが重要ですが、行内では列インデックスを追加するだけです。したがって、Nは列の数、すなわち行のサイズを定義し、コンパイラが各セルを正しくアドレス指定できるように、tab[][N]のような宣言で十分です。

どうにかして助けてください。

+0

あなたの答えをありがとう。もし私が正しいとすれば、コンパイラは、最初の[]で渡される行の数を知る必要はありません! Ok ...配列の内容に何も変わりませんか?その単なる単純化? – Doctor

+0

@Doctor:はい、配列の内容は変更されません。単純化または抽象化であれば、型が 'tab [] [N]'なら、この配列の行数に関係なく、 'N'列の配列を渡すことができます。型が 'tab [R] [C]'ならば、ちょうど 'C'列と' R'行の配列を渡すことができます。 –