当你声明一个数组时我会得到它,例如:
int Numbers[5];
int *intPtr = NULL;
您无法执行以下操作:
Numbers++;
Numbers + 1 = intPtr;
Numbers = NULL;
etc
使数组的基址(和后续地址)保持不变(或不可修改?)的动机是什么?让我们说出于一些奇怪的原因,我想这样做:
Numbers + 8 = intPtr;
为什么编译器不允许访问超过分配的整数(在这种情况下为5)?
答案 0 :(得分:5)
在
的情况下int Numbers[5];
您没有定义指针。你正在定义一个数组。实际上,Numbers
的类型是int[5]
。而你正在定义的那个数组,它在某个地方的内存中有一个位置。该内存的 base 由(int *)Numbers
指向。由于内存无法移动到任何地方,移动(int *)Numbers
也是非法的。
请注意,内存位置的这种不变性不仅限于数组。例如:
int x;
现在,你如何在记忆中移动x
?如果您执行x++
,则会增加x
,但不会移动它。并且尝试使用指向x
的指针进行任何数学运算肯定不会在内存中移动x
。 x
(或Numbers
)在内存中的位置是在创建x
时设置的,无论您尝试多么努力,都无法移动它。这适用于任何类型 - 您无法移动单个整数,也无法移动数组。
答案 1 :(得分:1)
Numbers是一个名字......它的类型是int [5]。数字++在这里意味着什么?是数字[1]还是数字[5]?从这个意义上讲,它不太清楚。同样,Numbers = NULL是什么意思?它是否意味着隐藏了为数组[5]分配的空间?这可能不是c语言标准的回复......但只是一种直观的感觉。
答案 2 :(得分:1)
编译器不允许您这样做。如果你这样做,你将丢失数组的所有5个元素。 数字也是一个变量。你不能改变变量的地址。您可以更改其中的值。
答案 3 :(得分: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]并不安全,因为它不是为您保留的,因此可能导致分段错误或数据损坏。
答案 4 :(得分: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);
请注意n
是指针,而numbers
不是指针而是数组。
答案 5 :(得分: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;
}
为什么你想尝试将int *
的值分配给int
的5元素数组的第9个元素,不过我就是这样。
答案 6 :(得分:1)
你不能这样做的原因是因为这可能会破坏(进程)内存。因此,如果我们分配“int Numbers [5]”,那么这将保留5个整数的连续内存。当你超出这个5个整数的区域时,你正在访问一个未分配给数组的内存区域 - 这个区域可能被其他一些变量使用。
如果阵列中需要额外的空间,则可以使用动态数组或链接列表。使用动态数组,您可以创建一个新数组,将所有元素复制到新存储,并释放旧数组。使用链表,我们为列表中的每个节点malloc一个新的内存区域。然后,使用下一个(或上一个)指针,我们使它指向列表中其他节点的内存位置。但是,在这两种情况下,我们都不会超越分配给我们的记忆。