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

5

我的理解是数组实际上只是指针

让我们把它排除在外。不,数组不是指针。数组是一系列对象,都是相同类型的,在内存中是连续的。

数组可以通过引用传递,但这不是通常的做法。通常所做的,也就是您正在做的,是将指针传递给数组的第一个元素。数组可以并且将根据需要“衰减”到指向其第一个元素的指针。这就是当你传递ratesshow1and时发生的事情show2

show1and内部show2list以指向 的指针开始rates[0]。您可以随意修改此指针以指向任何其他double.

如果你想通过引用传递一个数组,它看起来像这样:

void show3(double (&list)[9]) { ... }

或者更通用的:

template<size_t SIZE>
void show3(double (&list)[SIZE]) { ... }

请注意,您不能做的是按值传递数组(除非它包含在另一个对象中)。如果您编写的函数看起来像是按值获取数组,例如

void show4(double list[9]) { ... }

它实际上是一个指针,那个数字 9 是没有意义的。原生数组很烂。

于 2013-11-13T05:41:55.177 回答
1

首先,当作为函数参数传递时,数组被转换为指向第一个元素的指针。顺便说一句,数组不是指针,例如,sizeof(rates)在您的代码中不是指针的大小。

其次,数组是按值传递的,因为您没有使用引用。

所以在函数show2中,你正在修改一个指针,这很好。

于 2013-11-13T05:42:51.290 回答
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 个字节),“a size”将是 4 或 8 个字节,具体取决于 32/64 位,“(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;
}

这输出“2,3,4”而不是“1,2,3”。

这是因为数组在作为函数参数传递时会衰减为指针。但是为了支持将数组作为数组接收的语法,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 数组的情况下,我们有 nul 终止符字节,而不是大小。

不幸的是,他们没有选择通过拒绝表示您正在接收一个大小信息完整的数组来使其明显:(

于 2013-11-13T07:24:34.213 回答