0
int a[10][5];
for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        cout << i[j[a]];
        cout << j[i[a]];
    }
}  

編集:値がすでに配列に初期化されていると仮定し、このcoutは有効ですか?

i[j[a]];私が懸念しているプログラムに関係なく、その部分だけを説明してください。

4

3 に答える 3

1
cout << i[j[a]];
cout << j[i[a]];

C ++では、X[Y]表記は字句的*(X+Y)次のようになります。

[C++11: 5.2.1/1]: [..]E1[E2]は(定義上)*((E1)+(E2)) [..]と同じです。

これは、加算が可換であるためと同じである、とY[X]同等であることを意味します。*(Y+X)*(X+Y)

何らかの理由で、作者はこの紛らわしいコードを書くことによって「賢い」ことを試みることに決めました。

可換性とX[Y]単独の定義による:

i[j[a]] => i[*(j+a)] => *(i+*(j+a)) => *(*(a+j)+i) => *(a[j] + i) => a[j][i]
j[i[a]] => j[*(i+a)] => *(j+*(i+a)) => *(*(a+i)+j) => *(a[i] + j) => a[i][j]

したがってcout、ステートメントは次のようになります。

cout << a[j][i];
cout << a[i][j];

5いずれの場合も、配列の各要素には整数しかないため、ループは配列の境界を超えて読み取ろうとしますがa、内側のループはまで行こうとします10

これの実際の結果は定義されていないので、サイレント成功、サイレント失敗、任意の値、セグメンテーション違反、パワーカット、ブラックホール、クリスマスのポニー、つま先の切断、または新しいバイクを取得できます。

ループ条件が修正されている場合でも、最初のステートメントが意味的に正しくないことに注意してください(最初の次元を外側のループに、2番目の次元を内側のループに割り当て続けると仮定します)。

于 2013-01-17T17:47:37.747 に答える
0

C配列には奇妙な癖があり、「反対」方向からアクセスできます。これは、配列のポインタ演算に深く根ざしています。たとえば、a[1]はと同等*(a + 1)です。同様に、1[a]と同等*(1 + a)です。加算の可換性により、これは非常にうまく機能します。詳細については、こちらをご覧ください

その知識をそのままにして、表現i[j[a]]を2つの異なる部分に分けることができます。j[a]*(j + a)、使用している配列の多次元的な性質により、別の配列を返すのと同じです。たとえば、この返された配列をこのように呼びますpi[p]次に、と同等のステートメントがあります*(i + p)。すべてを元に戻すと、i[j[a]]と同等であることがわかります*(i + *(j + a))。確かに、これはそれi[j[a]]が単なる難読化された書き方であることを意味しa[j][i]ます。

于 2012-09-09T04:29:29.420 に答える
0

C / C ++では、ポインターを整数インデックスで下付き文字にするか、整数インデックスをポインターで下付き文字にすることができ、意味(セマンティクス)はまったく同じです。なぜ非常識な構文が有効なのかはわかりませんが、有効であり、明らかにそうです。

#include <stdio.h>

int main(int argc, char** argv)
{
  int i = 1, array[10];
  printf("%ld\n", &(i[array])-&(array[i]));
  return 0;
}

出力:

0
于 2012-09-09T05:02:57.060 に答える