14

次のコードを検討してください。

void populate(int *arr)
{
   for(int j=0;j<4;++j)
       arr[j]=0;
}

int main()
{
   int array[2][2];
   populate(&array[0][0]);
}

コードが有効かどうかについて、地域コミュニティで議論がありました(名前を言うことになっていますか?)。ある男は、それが違反しているのでUBを呼び出すと言っていました

C ++標準($ 5.7 / 5 [expr.add])

「ポインタオペランドと結果の両方が同じ配列オブジェクトの要素を指している場合、または配列オブジェクトの最後の要素を1つ過ぎている場合、評価はオーバーフローを生成しません。それ以外の場合、動作は未定義です。」

しかし、コードに問題はありません。コードは私にとって完全に問題ありません。

だから、私はこのコードが有効かどうか知りたいだけですか?私は何かが足りないのですか?

4

4 に答える 4

15

あなたarrayはの2つの配列ですがint[2]、関数populate()はそれをの1つの配列として扱いますint[4]。コンパイラがの要素の整列を正確に決定する方法によってはarray、これは有効な仮定ではない場合があります。

具体的には、jが2でアクセスしようとすると、これはのarr[2]範囲外であるため無効です。mainarray[0]

于 2010-01-10T04:48:38.423 に答える
9

配列の配列があります。 配列は連続しているため、メモリ内で続きますarray[1]。配列が連続しているため、のarray[0]場合p == array[0]は、がp[1]続きます。p[0]だから、あなたは正しいです:のすべてのメモリarrayは隣接しています。

写真でarrayはこんな感じ。

+-----------------+-----------------+
|      [0]        |      [1]        |
+-----------------+-----------------+

さて、分解してみましょうarray[0]array[1]それらは個別に次のようになります:

+--------+--------+
|  [0]   |  [1]   |        
+--------+--------+

したがって、最終的な画像は次のとおりです。

+--------+--------+--------+--------+
| [0][0] | [0][1] | [1][0] | [1][1] |
+--------+--------+--------+--------+

さて、問題は、あなたが今のようにこの連続した記憶にアクセスできるかということです。答えは、それは標準によって保証されていないということです。配列は連続していますが、標準では、これまでの方法でインデックスを作成することはできません。言い換えると:

&array[0][0]+2 == &array[1][0]、ただし、(&a[0][0] + 2) + 1は未定義ですが、&a[1][0] + 1は有効です。これが奇妙に思える場合はそうですが、標準から投稿した引用によると、配列内または配列の1つ先のポインターのみを計算できます(「1つ前の」ポインターを間接参照せずに) 。

実際には、これがどこでも失敗することはないと思いますが、少なくとも標準によれば、未定義の動作のためにコードは無効です。

この投稿comp.lang.cも参照してください。

于 2010-01-10T05:22:00.770 に答える
3

それが常に機能するとは限りません。Cには、2D配列ではなく、配列の配列があります。サブ配列は、メモリ内で連続するように常に指定されているわけではありません(静的配列は、C / C ++標準を確認してください)。この特定の例では、正しく機能していると思われます。ただし、渡されるメモリを動的に割り当てた場合、malloc(またはnew)によってサブ配列がかなり離れている可能性があるため、失敗する可能性があります。

ただし、「2d」メモリを直線的にウォークダウンする場合は、1D配列に対して2Dアクセサーを構築できます。これは正常に機能し、memsetなどは1D配列に対して機能します。

于 2010-01-10T04:51:07.523 に答える
0

すべてにおいてC、線形メモリセグメントに格納されます。すべてが線形に格納されているため、の a[0][0]アドレスと同じになるアドレスを渡します。ただし、メモリを動的に割り当てると、すべての行が連続した場所に格納されない可能性があるため、失敗します。その後、になります。a[0]a[i][j]a[i*ColSize+j]a[i][j]*(&a[i]+j)

于 2010-01-10T05:36:26.410 に答える