2008-09-11 34 views
3

これはthis answer to a previous question of mineから発生しました。 array[4][4]array[16]と同じに扱うことはコンパイラで保証されていますか?多次元配列と単次元配列のキャスト

たとえば、api_func()の次のいずれかの呼び出しが安全なのでしょうか?

void api_func(const double matrix[4][4]); 

// ... 

{ 
    typedef double Matrix[4][4]; 

    double* array1 = new double[16]; 
    double array2[16]; 

    // ... 

    api_func(reinterpret_cast<Matrix&>(array1)); 
    api_func(reinterpret_cast<Matrix&>(array2)); 
} 

答えて

3

sizeofオペレータを参照:

アレイに適用された場合、結果は、アレイ内のバイトの総数です。これは、n要素の配列のサイズが要素のサイズのn倍であることを意味します。

これより、double[4][4]double[16]は同じ基本的な表現を持つ必要があると思います。

すなわち、

sizeof(double[4]) = 4*sizeof(double) 

sizeof(double[4][4]) = 4*sizeof(double[4]) 

与えられ、その後、我々は

sizeof(double[4][4]) = 4*4*sizeof(double) = 16*sizeof(double) = sizeof(double[16]) 

を持って、私は標準準拠のコンパイラはこれらを同じに実装しなければならないと思う、と私は考えますこれは、コンパイラが誤って中断することではないということです。多次元配列を実装する標準的な方法は、期待通りに機能します。標準を破るには、余計な作業が必要になります。

C++標準では、配列が連続的に割り当てられた要素で構成されていることも記載されています。ポインタやパディングを使用して奇妙なことを行う可能性が排除されます。

0

私は[5] [5]並ぶ各行の単語を作るためのマトリックスのようなもののために追加されたパディング心配だろうが、それは単に私自身の迷信である可能性があります。

2

多次元配列を持つことで、パディングに問題があるとは思わない。

アレイ内の各要素は、アーキテクチャによって課されたパディング要件を満たす必要があります。配列[N] [M]は常に[M * N]の1つと同じメモリ表現になります。

1

各配列要素は、コンパイラによってメモリに順次配置される必要があります。 2つの宣言は、異なるタイプは同じ基本的なメモリ構造ですが、 C++標準から

0

大きな質問は次のとおりです。本当にこのようなキャストを実行する必要がありますか?

でもそれを取り除くことはできますが、完全に回避するためには読みやすく保守的です。たとえば、実際の型としてdouble [m * n]を一貫して使用し、この型をラップするクラスを操作し、[]演算子をオーバーロードして使いやすくすることができます。その場合、my_matrix [3] [5]のようなコードが期待どおりに動作するように、1行をカプセル化するために中間クラスが必要な場合もあります。

1

@Konradルドルフ:

は、私は自分自身を混ぜたもの2(主要行メジャー/列)を取得しますが、私はこれを知っています:それは明確に定義されます。

int x [3] [5]は、サイズが3の配列で、その要素はサイズが5のint配列です。(§6.5.2.1)配列についてのすべてのルールを追加し、 2番目の添え字が連続した整数を参照し、最初の添え字が連続する5つのintオブジェクトを参照することになります。 (したがって、3が大きい番号であり、x [1] [0]とx [2] [0]の間に5つの整数があります)