If I have a 2d array B defined as :
int B[2][3] = {{1,3,5},{2,4,6}};Is
int **p = Bsame asint (*p)[3] = B?int **f = B; printf("%d ",*f+1);gives
5as output whileprintf("%d ",*f)gives 1 as answer. Why is that happening?printf("%d ",**f);returns a segmentation fault! Why?
2 に答える
No.
int **p = B;はエラーです。(コンパイル エラーと論理エラーの両方)。int **は を指している必要がありますint *。ただし、 にはint *保存されていませんB。ポインタを含まないB連続した のグループです。intint **f = B;コンパイルエラーが発生する必要があります。結果として生成される実行可能ファイルの動作は、完全に定義されていません。2を参照してください。
と が表示される理由を説明し1ます5。(C 標準ではこれを定義していませんが、コンパイラはとにかく先に進みます)。おそらく、コンパイラは行を次のように扱います
int **f = (int **)B;
次に、式は(実際には s を保持する)*fのストレージからバイトを読み取り、それらがポインター表現を構成するバイトであると見なします。これはさらに未定義の動作です (strict-aliasing ルールの違反)。おそらくこれの結果、それは address へのポインタです。Bint*f0x00000001
次に、を使用してポインターを出力する%dと、未定義の動作がさらに発生します。お使いのシステムがに渡す場合と1同じ方法を使用するためです。 intprintfint *
に 1 を追加すると(int *)0x00000001、 が得られ(int *)0x00000005ます。これは、ポインターをインクリメントするということは、その型の次の要素を指すことを意味するためです。
このポインターを逆参照すると、そのアドレスが有効なアドレス空間の外にあるため、セグメンテーション違反が発生します。
1) とint **p = b同じint (*p)[3] = bですか? - No.int **p = bは誤りです。
これはint **p整数へのポインタへのポインタですがint (*p)[3]、3 つの整数の配列へのポインタです!
2)int **f = B;これはエラーです。未定義の動作が発生する可能性があります。
3) printf("%d ",**f);- (2)と同じです。int **f = B;はエラーなので、未定義の動作です!
注: このタイプのエラーを回避するには、コンパイラ オプションでいくつかの警告フラグを有効にして試してください。