1

Cでこれを行うことができますか:

void myFunc(int *vp) {
    // do some stuff with vp
}

int main() {

    int v[5] = {1,2,3,4,5};
    myFunc(v);

    return 0;
}

つまり、何が正しいでしょうか?myFunc(&v); ?

ありがとう!!

4

3 に答える 3

4

配列を引数として渡すと、配列はポインターに分解されます。ただし、配列の減衰は、配列のアドレスを取得することと同じではありません。

「減衰」は、関数の引数として渡されたときに一部の型がどのように変換されるかです。vの型はですが、関数に渡すと になりますint [5]int*これは多くの人が好まない行為ですが、どうしようもありません。

一方、 の型は&vis int (*)[5]、つまり 5 つの整数の配列へのポインタであることに注意してください。この型は減衰しません。つまり、関数パラメーターとして渡すと、別の型に自動的に変換されません (また、ポインターが必要なため、例で使用した場合に機能しないのもそのためです)。整数の配列へのポインターではなく、整数へ)。

「正しい」こと (減衰が問題ないと仮定) はmyFunc(v)、スニペットで行っているのと同じように を行うことです。これを行うと、配列の境界情報が失われることに注意してください。

于 2013-09-26T04:36:51.147 に答える
1

はい...あなたのコードは正しいです。

ここでv==&v[0]、配列名は配列の最初の要素のアドレスと同じです

    myFunc(v); 

配列名を引数として渡すということは、配列の最初の要素のアドレスを渡すことを意味します。

    void myFunc(int *vp)  

ここではポインターを使用しています。渡された配列の最初の要素のアドレスを格納するため、ポインターの位置をインクリメントすることにより、配列で覆われたブロックにアクセスできます。

    myFunc(&v);   

    &v==&&v[0];

&v は、配列の最初の要素のアドレスのアドレスです。

  void myFunc(int *vp)      

ここで 配列の最初の要素のアドレスを取得しました. これは配列を指していません. 代わりに、メモリの場所を指します。ポインタをインクリメントして配列にアクセスすることはできません。

于 2013-09-26T04:53:14.377 に答える
1

あなたのコードは正しい それは動作します....しかし、境界条件をチェックするために細心の注意を払う必要があります。コードを見てください。

void myFunc(int *vp) {
    vp[5] = 30;
}

int main() {

    int v[5] = {1,2,3,4,5};
    int a = 10;
    printf("Value of a before fun call %d\n", a);
    myFunc(v);
    printf("Value of a before fun call %d\n", a);
    return 0;
}

同様に

void myFunc(int *vp) {
    vp[5] = 30;
    myFunc2(vp);
}

void myFunc2(int *vp) {
    vp[6] = 30;
}

int main() {

    int v[5] = {1,2,3,4,5};
    int a = 10;
    printf("Value of a before fun call %d\n", a);
    myFunc(v);
    printf("Value of a before fun call %d\n", a);
    return 0;
}

これにより、スタック破壊によるセグメンテーション違反が発生します。ローカル変数はスタックにあるため。

于 2013-09-26T09:11:59.323 に答える