19

まず第一に、私の英語で文法の間違いなどをしたら申し訳ありません...

私の質問は、2 次元配列がある場合、私が正しければ、コンピューターと C/C++ の観点からは、それは単なる長い 1 次元配列であり、インデックスはコンパイラが具象にマップするのを支援しているだけだということです。住所。

このコード フラグメントは Visual C++ で動作しますが、このコードが移植可能であり、標準(C++98) に準拠 しており 、他のアーキテクチャやオペレーティング システムで驚きを引き起こさないかどうかを知りたいです。

int arr[][3] = { 1, 5, 3, 7, 5, 2, 7, 8, 9 };
const int ARR_NUM = sizeof(arr) / sizeof(int);

int* ptr = reinterpret_cast<int*>(arr);    // NOT: int(*)[][3] !!!
for (int i = 0; i < ARR_NUM; ++i) {
    cout << ptr[i] << endl;
}
4

4 に答える 4

15

標準語

多次元配列の要素は行優先順に格納されるため、手動のインデックス付けは移植可能です。

C++98、8.3.4/1:

配列型のオブジェクトには、連続して割り当てられた、型 T の N 個のサブオブジェクトの空でないセットが含まれます。

明らかに、多次元配列の場合、これは再帰的に適用されます。

ただし、この使用法reinterpret_castは移植性がありません。標準は、(C++98、5.2.10/1) と述べています。

[...] それ以外の場合、結果は右辺値であり、[...]、配列からポインターへ、[...] の標準変換が式 v に対して実行されます。

つまり、すぐに渡すarrと、配列がその最初の要素へのポインターに減衰します。次に、(C++98、5.2.10/3) がキャッチオールになります。

によって実行されるマッピングreinterpret_castは実装定義です。

セクションの残りの部分では、これに対するいくつかの例外をリストし、常に明確に定義されたキャストを指定します。ここではそれらのどれも当てはまらないので、結論は、技術的にはデフォルトで実装定義であるということです。

最終的な結論

理論的に言えば、これは移植性がありません。実際には、アーキテクチャが同じ (x86 など) である限り、キャストが確実に機能することを期待できます。

幸いなことに、他の人 が言及したようint* ptr = arr[0]に、同じことを行い、移植性が保証されているため、そのようなことを想定する必要はありません。

于 2012-05-16T12:46:45.830 に答える
4

本当に厳密にしたい場合は、 reinterpret_cast は標準であまり明確に定義されていません。これはどこでも機能しますが、それに対して衒学的な主張をすることができます。

使用する

int *ptr = arr[0];

非常に安全な側にいること。連続した配列レイアウトが保証されます。

于 2012-05-16T12:49:52.073 に答える
0

私が間違っていなければreinterpret_cast、ポータブル操作ではありません。

于 2012-05-16T12:39:26.813 に答える
0

多次元配列が連続したメモリ レイアウトを持つという仮定に関しては、標準に準拠しており、移植可能です。これは C の時代からずっと当てはまり、C++ でもこれは変わりません。

ただし、reinterpret_cast移植性がないため、全体として、コードがどこでも動作することが保証されているわけではありません。

于 2012-05-16T12:32:43.913 に答える