我想从键盘(或从文件:./a)中获取数字。& lt;文件)并将它们存储在数组中。其思想是数组的长度是未知的。
#include <stdio.h>
#include <stdlib.h>
int* newElem(){
int* elm= malloc(sizeof(int));
if (elm == NULL) {
printf("nError: memory allocation failed.n");
exit(-1);
}
return elm;
}
int main(){
int *array,x,size,i=0;
while( scanf("%d",&x)==1 ){
array= newElem();
array[i]=x;
i++;
}
size=i;
free(array);
printf("size=%d",size);
return(0);
}
为什么当我输入:1 2 3 4 5 6 7 8
在你的代码中
array= newElem();
每次都会覆盖现有的指针(内存)。因此,array[i]
无效,这本质上是越界访问,这反过来又调用了未定义的行为。您需要使用realloc()
来重新调整分配的内存大小。
简单。
array= newElem();
array[i]=x;
i++;
newElem()总是返回int[1],而您试图访问[n]
首先,您需要知道数组是由连续的地址组成的序列。这意味着如果第一个元素的地址是0,那么第二个元素的地址将是1,然后是2,依此类推…
当你在C中说x[10]
时,你实际上是在说*(x + 10)
,这意味着"从第一个元素(0)开始,向前移动10个地址(+ 10),并将该地址的内容(*运算符)作为int。
所以你看,元素之间有一个数学关系,它们在内存中都是紧挨着的。
现在,到你的代码…
当你调用array= newElem();
时,你的指针array
指向新分配的地址。但是,在之前指向的任何先前的地址array
都是丢失的,这会导致您的意外行为和内存泄漏。
当你第一次调用array= newElem()
时,假设在地址A
处分配了一个整数,下一次在地址B
处分配了一个新的整数,以此类推…
在第一次迭代时,使用i = 0
:
while( scanf("%d",&x)==1 ){
array= newElem();
// array points to A
array[i]=x;
// array[0] = x
// or *(array + 0) = x
// same as *(array) = x
i++;
// i = 1
}
现在你很可能会有一个错误(i = 1
):
while( scanf("%d",&x)==1 ){
array= newElem();
// address A is lost, and now array points to B
array[i]=x;
// array[1] = x; -> likely an ERROR
// *(array + 1) = x
i++;
// i = 2
}
在第二次迭代中,你试图访问array
指向的新地址旁边的地址,这将是C,这就是为什么你得到了一个违规。
您的代码不维护数组元素之间的关系,您实际上是在每次迭代中创建单个整数,然后尝试访问内存地址,但实际上是访问无效的内存地址。
一开始这不是一个非常简单的概念,如果你需要进一步澄清,请注释