2
void pass_arr(int arr[]);

void pass_arr_test()
{
    int arr[5] = {1,2,3,4,5};

    printf( "arr  = %p\n"
            "&arr = %p\n\n", arr, &arr);

    pass_arr(arr);
}

void pass_arr(int arr[])
{
    printf( "passed arr  = %p\n"
            "passed &arr = %p\n\n", arr, &arr);
}

出力:
arr = 0x28ccd0
&arr = 0x28ccd0

合格 arr = 0x28ccd0
合格 &arr = 0x28ccc0


arr が作成されたブロックで評価されたときに arr の値とアドレスが同じアドレスを指しているのに、渡されたときに値とアドレスが2つの異なるアドレスを指している理由を誰かが説明できますか?

4

3 に答える 3

3

これは、関数内arrが実際にはポインタであり、配列ではないためです。ポインターのアドレスを取得しても、配列の場合とは異なり、同じアドレスは得られません。

于 2012-09-22T11:13:29.183 に答える
2

sizeof_Alignof、または単項演算子のオペランドである場合、または&宣言で別の配列を初期化するために使用される文字列リテラルである場合を除き、型 "N 要素配列 "のTは型に変換 ("decay") されます。 "pointer to T" であり、式の値は配列1の最初の要素のアドレスになります。

電話すると

`pass_arr(arr)`;

arrは、型「の 5 要素配列int」から「へのポインタint」、またはに変換されますint *

配列の最初の要素のアドレスは、配列自体のアドレスであることに注意してください。そのため、とintの結果を出力すると同じが得られますが、が異なることに注意してください。式は type に変換されますが、 typeがあります。これは、ポインター演算などに関係します。arr&arrpass_arr_testarrint *&arrint (*)[5]

第 2 に、関数プロトタイプのコンテキストでは、フォームT a[]andの宣言は;T a[N]として解釈されます。実際には、配列ではなくポインタとして宣言されています。2T *aa

覚えておくべき重要なことは、配列はポインターではないということです。むしろ、ほとんどのコンテキストでは、配列は必要に応じてポインターに変換されます。


1 - N1570、6.3.2.1 左辺値、配列、および関数指示子、¶ 3
2 - N1570、6.7.6.3 関数宣言子 (プロトタイプを含む)、¶ 7

于 2012-09-22T13:18:56.847 に答える
0

これは、pass_arr メソッドの arr がスタック上のローカル ポインター変数であり、その値がpass_arr_test メソッドから渡されpass by valueた場所であるセマンティクスによるものです。arrしたがって、arrpass_arr と pass_arr_test の両方の変数は同じ場所を指しているため、値は同じです。これらは 2 つの異なるポインタであるため、メモリ アドレスが異なります。配列定義の場合、 arr は配列の先頭への単なるエイリアスであるため、その場所と値は同じです。

于 2012-09-22T11:19:46.363 に答える