If I have a 2d array B defined as :
int B[2][3] = {{1,3,5},{2,4,6}};
Is
int **p = B
same asint (*p)[3] = B
?int **f = B; printf("%d ",*f+1);
gives
5
as 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
連続した のグループです。int
int **f = B;
コンパイルエラーが発生する必要があります。結果として生成される実行可能ファイルの動作は、完全に定義されていません。2を参照してください。
と が表示される理由を説明し1
ます5
。(C 標準ではこれを定義していませんが、コンパイラはとにかく先に進みます)。おそらく、コンパイラは行を次のように扱います
int **f = (int **)B;
次に、式は(実際には s を保持する)*f
のストレージからバイトを読み取り、それらがポインター表現を構成するバイトであると見なします。これはさらに未定義の動作です (strict-aliasing ルールの違反)。おそらくこれの結果、それは address へのポインタです。B
int
*f
0x00000001
次に、を使用してポインターを出力する%d
と、未定義の動作がさらに発生します。お使いのシステムがに渡す場合と1
同じ方法を使用するためです。 int
printf
int *
に 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;
はエラーなので、未定義の動作です!
注: このタイプのエラーを回避するには、コンパイラ オプションでいくつかの警告フラグを有効にして試してください。