0

私は独学で C++ を学んでおり、配列とポインターについていくつか質問がありました。私の理解では、配列は実際には単なるポインターですが、配列は変更できない アドレス定数です。

show2()この場合、関数でポインターのアドレスを変更できたのはなぜだろうと思っていましたlist。変数とは異なり、配列は参照渡しだと思っていたので、関数show2()のアドレスをインクリメントしたため、関数を呼び出すときにコンパイラ エラーが発生することが予想されていましたlist。しかし、コードは問題なく動作します。誰か説明してくれませんか?

ありがとうございました!

#include<iostream>
#include<iomanip>

using namespace std;

void show1(double *list, int SIZE)
{
    for(int i=0; i < SIZE; i++)
    {
        cout << setw(5) << *(list+i);
    }
    cout << endl;
    return;
}

void show2(double *list, int SIZE)
{
    double *ptr = list;

    for(int i=0; i < SIZE; i++)
        cout << setw(5) << *list++;
    cout << endl;
    return;
}

int main()
{
    double rates[] = {6.5, 7.2, 7.5,  8.3, 8.6, 
                      9.4, 9.6, 9.8, 10.0};
    const int SIZE = sizeof(rates) / sizeof(double);

    show1(rates, SIZE);
    show2(rates, SIZE);    
    return 0;
}
4

3 に答える 3

0

配列はポインターではありません。C++ は C から " Array-Pointer Equivalence " を継承しています。これは、よく知られている配列変数がポインターに減衰できることを意味します。これは、主にオフセット計算の目的と、値による配列の受け渡しを回避するためです。

int array[64];
int* a = array; // equivalent to a = &array[0];

配列はポインターではありません。ポインター コンテキストで配列変数名を使用すると、ポインターに "減衰" します。つまり、配列オブジェクトから利用できる拡張属性が失われます。

int array[64];
int* a = array;
std::cout << "array size = " << sizeof(array) << "\n";
std::cout <<  "a size = " << sizeof(a) << "\n";
std::cout << "(int*)(array) size = " << sizeof((int*)array)) << "\n";

「配列サイズ」は 256 (int は 4 バイト、そのうちの 64 = 256 バイト)、「サイズ」は 32/64 ビットに応じて 4 または 8 バイト、「(int*)(array)」サイズはポインターと同じサイズにします。

多くの人は、配列は値渡しであると考えています。これは真実ではありません: http://ideone.com/hAeH18

#include <iostream>

void bump(int arr[3]) {
    for (size_t i = 0; i < 3; ++i)
        arr[i]++;
}

int main() {
    int array[] = { 1, 2, 3 };
    bump(array);
    for (size_t i = 0; i < 3; ++i)
        std::cout << array[i] << "\n";

    return 0;
}

これは、「1、2、3」ではなく「2、3、4」を出力します。

これは、配列が関数の引数として渡されるとポインターに減衰するために発生します。しかし、配列を配列として受け取るための構文をサポートするために、C はいくつかのコンテキストでポインターを配列のように扱うことができなければなりません:

void f1(int* a) { a[0]++; }

void f2(int* a) { (*a)++; }

void f3(int a[]) { a[0]++; }

void f4(int a[]) { (*a)++; }

void f5(int a[1]) { a[0]++; }

void f6(int a[1]) { (*a)++; }

これらの関数はすべて同じコードを生成します。

C では、これは配列情報がコンパイル時に失われるという事実に由来します。したがって、この関数:

void f(int array[])

受信している配列の大きさを知る方法はありません。彼らは、プログラマーがこのことを認識し、サイズ情報を渡す方法/場合に注意することを望んでいました。たとえば、char 配列の場合、サイズの代わりにヌル ターミネータ バイトがあります。

残念ながら、彼らは、サイズ情報がそのままの配列を受け取っているように見える表現を非表示にすることによって、それを明確にすることを選択しませんでした:(

于 2013-11-13T07:24:34.213 に答える