82
#include <iostream>
using namespace std;

void printarray (int arg[], int length) {
    for (int n = 0; n < length; n++) {
        cout << arg[n] << " ";
        cout << "\n";
    }
}

int main ()
{
     int firstarray[] = {5, 10, 15};
     int secondarray[] = {2, 4, 6, 8, 10};
     printarray(firstarray, 3);
     printarray(secondarray, 5);

     return 0;
}

このコードは機能しますが、配列がどのように渡されるのかを理解したいと思います。

printarraymain関数から関数が呼び出されると、配列の名前が渡されます。配列の名前は、配列の最初の要素のアドレスを指します。これはどのように同等int arg[]ですか?

4

5 に答える 5

60

構文

int[]

int[X] // Where X is a compile-time positive integer

とまったく同じです

int*

関数パラメーターリストにある場合(オプションの名前は省略しました)。

さらに、配列名は、関数に渡されると(参照によって渡されない場合)、最初の要素へのポインターに減衰するため、とsの両方int firstarray[3]int secondarray[5]減衰しint*ます。

また、同じインデックスを使用すると、配列の逆参照と添え字構文(添え字構文はx[y])を使用したポインターの逆参照の両方で、同じ要素の左辺値が生成されることもあります。

これらの3つのルールを組み合わせて、コードを合法化し、期待どおりに機能させます。配列がポインタに減衰した後はわからない配列の長さとともに、関数へのポインタを渡すだけです。

于 2013-01-13T22:49:59.717 に答える
23

次のように配列の位置にアクセスするときに、これを追加したいだけです

arg[n]

と同じです

*(arg + n) thanは、deargアドレスから始まるnのオフセットを意味します。

そうarg[0]なります*arg

于 2013-01-13T22:52:58.417 に答える
19

質問はすでに回答済みですが、より正確な用語とC++標準への参照を含む回答を追加したいと思いました。

ここでは、配列パラメーターがポインターパラメーターに調整されることと、配列引数がポインター引数に変換されることの2つが行われています。これらは2つのまったく異なるメカニズムであり、1つはパラメーターの実際のタイプの調整であり、もう1つは最初の要素への一時的なポインターを導入する標準の変換です。

関数宣言の調整:

dcl.fct#5

各パラメーターのタイプを決定した後、タイプ「array of T」(...)のパラメーターは、「Tへのポインター」になるように調整されます。

したがってint arg[]、に調整されますint* arg

関数の引数の変換:

conv.array#1

「NTの配列」または「Tの未知の境界の配列」タイプの左辺値または右辺値は、「Tへのポインター」タイプのprvalueに変換できます。一時的な実体化変換が適用されます。結果は、配列の最初の要素へのポインターです。

したがって、では、タイプ「array of 3 int」printarray(firstarray, 3);の左辺値は、最初の要素を指すタイプ「pointertoint」のprvalue(一時的)に変換されます。firstarray

于 2018-03-10T22:29:42.290 に答える
11

firstarraysecondarray渡されると、intへのポインタに変換されprintarray()ます。

printarray(int arg[], ...)と同等ですprintarray(int *arg, ...)

ただし、これはC++に固有のものではありません。Cには、配列名を関数に渡すための同じ規則があります。

于 2013-01-13T22:51:10.853 に答える
0

簡単な答えは、配列は常に参照によって渡され、intarg[]はコンパイラに配列を期待することを通知するだけです。

于 2019-11-24T04:09:25.860 に答える