3

これは、私の以前の質問に対するこの回答から生まれました。コンパイラが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));
}
4

6 に答える 6

3

sizeof演算子を参照して、C++ 標準から:

配列に適用すると、結果は配列内の合計バイト数になります。これは、要素の配列のサイズが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++ 標準では、配列は連続して割り当てられた要素で構成されているとも述べています。これにより、ポインターとパディングを使用して奇妙なことを行う可能性がなくなります。

于 2008-09-11T01:42:11.113 に答える
2

多次元配列を持つことによって導入されたパディングに問題はないと思います。

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

于 2008-09-11T00:53:49.513 に答える
1

@コンラッド・ルドルフ:

私はそれらの2つ(行メジャー/列メジャー)を自分で混同していますが、私はこれを知っています:それは明確に定義されています。

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

于 2008-09-11T23:43:24.430 に答える
1

各配列要素は、コンパイラによってメモリ内に順番に配置される必要があります。型が異なる 2 つの宣言は、基になる同じメモリ構造です。

于 2008-09-11T00:53:53.180 に答える
0

Matrix[5][5] のようなものに各行の単語を揃えるためにパディングが追加されることを心配しますが、それは単に私の迷信かもしれません。

于 2008-09-11T00:12:30.003 に答える
0

より大きな問題は、本当にそのようなキャストを実行する必要があるかということです。

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

于 2008-09-11T07:24:35.517 に答える