1

当你声明一个数组时,我明白了,例如:

int Numbers[5];
int *intPtr = NULL;

您不能执行以下操作:

Numbers++;
Numbers + 1 = intPtr;
Numbers = NULL;
etc

使数组的基地址(和后续地址)成为常量(或不可修改?)的动机是什么让我们说出于某种奇怪的原因,我想这样做:

Numbers + 8 = intPtr;

为什么编译器不允许访问超过分配的整数数量(在这种情况下为 5)?

4

7 回答 7

5

如果是

int Numbers[5];

您没有定义指针。您正在定义一个数组。实际上, 的类型Numbersint[5]。你正在定义的那个数组,它在内存中的某个位置有一个位置。该内存的基址由 指向(int *)Numbers。由于内存不能移动到任何地方,移动(int *)Numbers也是非法的。

请注意,内存位置的这种不变性不仅限于数组。例如:

int x;

现在,你将如何x在记忆中移动?如果你这样做x++,那会增加x,但它不会移动它。并且尝试使用指向的指针进行任何数学运算x肯定不会x在内存中移动。x(or Numbers)在内存中的位置x是在创建时设置的,无论你怎么努力都无法移动它。这适用于任何类型——你不能移动单个整数,也不能移动数组。

于 2013-08-06T12:52:37.067 回答
1

首先我们谈谈标准所说的:6.3.2.1/3“其他操作数/左值、数组和函数指示符”:

Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.

现在为什么不可修改?

因为如前所述,它是指向数组初始元素的指针,所以对该指针的任何更改都会导致原始数组的丢失。我们可以对该地址的副本进行递增和递减来访问该数组的元素。

最后一个问题:

你想在数组的范围之外找到什么。你已经请求了 5 个元素,所以有 [0] 到 [4] 的空间。访问 [5] 并不安全,因为它不是为您保留的,因此可能会导致分段错误或数据损坏。

于 2013-08-06T12:37:47.300 回答
1

您无法更改 的值,Numbers因为Numbers它不是左值。如果你尝试类似的东西Numbers++,编译器会抱怨你试图分配给不是左值的东西。

不是左值的原因Numbers是它是数组的名称。如果更改 的值Numbers,您将无法引用数组,这使数组毫无意义。但是,您可以复制 的值Numbers并对其进行修改,例如:

int numbers[5];
int *n = (int*)malloc(sizeof(int) * 5);
printf("numbers is: %p\n", n);
n++;                            // this is OK
printf("numbers is: %p\n", n);

注意 thatn是一个指针,whilenumbers不是指针而是一个数组。

于 2013-08-06T12:39:08.717 回答
1

您不能这样做的原因是因为这可能会破坏(进程)内存。因此,如果我们分配“int Numbers[5]”,那么这会保留 5 个整数的连续内存。当您超出这个 5 个整数的区域时,您正在访问一个未分配给数组的内存区域 - 该区域可能正在被其他一些变量使用。

如果您的数组需要额外的空间,那么您可以使用动态数组或链表。使用动态数组,您可以创建一个新数组,将所有元素复制到新存储中,然后释放旧数组。使用链表,我们为链表中的每个节点分配一个新的内存区域。然后,使用下一个(或上一个)指针,我们使它指向列表中其他节点的内存位置。但是,在这两种情况下,我们都不会超出分配给我们的内存。

于 2013-08-07T04:09:08.660 回答
1

你不能做这样的事情:

Numbers + 8 = intPtr;

使用任何变量,不要介意数组。也许你的意思是这样的,这对指针和数组都是合法的:

int main(void) {
    int array[5];
    int * p;

    p = array;

    *(p + 3) = 4;        /* works */
    *(array + 4) = 5;    /* also works */

    return 0;
}

但是,为什么您想尝试将 an 的值分配给int *5 元素数组的第 9 个元素,这int超出了我的理解。

于 2013-08-06T14:23:47.787 回答
1

Numbers 是一个名字……它的类型是 int [5]。Number++ 在这里意味着什么?是转到 Numbers[1] 还是超出 Numbers[5]?从这个意义上说,就不清楚了。同样, Numbers=NULL 是什么意思?这是否意味着隐式释放为数组 Numbers[5] 分配的空间?这可能不是交流语言标准的回复......而只是一种直观的感觉。

于 2013-08-06T12:27:16.113 回答
1

编译器不允许您这样做。Cos,如果你这样做,你将丢失数组的所有 5 个元素。Numbers也是一个变量。您不能更改变量的地址。您可以更改其中的值。

于 2013-08-06T12:29:22.620 回答