int array[100];
int *array;
我对于
int array[100]
和 int *array
的区别感到困惑。基本上,当我使用
int array[100]
时(100
只是一个 int
类型的示例),我只是为 100 个整数在内存中保留了空间,但是我可以使用 int *array
,并且没有指定该数组的任何类型和大小,但我仍然可以执行 array[9999] = 30
,这仍然是有意义的。那么这两者之间有什么区别呢?
int array[100];
int *array;
int array[100]
和 int *array
的区别感到困惑。int array[100]
时(100
只是一个 int
类型的示例),我只是为 100 个整数在内存中保留了空间,但是我可以使用 int *array
,并且没有指定该数组的任何类型和大小,但我仍然可以执行 array[9999] = 30
,这仍然是有意义的。指针是一个指针,它指向其他地方(比如数组的第一个元素)。编译器没有关于它可能指向哪里或者指向的数据大小的任何信息。
数组是一组相同类型的连续元素的数组。编译器知道它的大小,因为它总是被指定的(尽管有时大小只是隐式指定的)。
数组可以被初始化,但不能被赋值。数组通常会衰减为指向它们第一个元素的指针。
数组衰减示例:
int array[10];
int *pointer = array; // Here the symbol array decays to the expression &array[0]
// Now the variable pointer is pointing to the first element of array
数组无法自然地传递给函数。当您声明函数参数时,如int arr[]
,编译器将将其转换为int *arr
。
所有这些信息以及更多信息都应该在任何好的书籍、教程或课程中提供。
extern int array[];
声明了一个在不同模块中定义或仅在同一模块中稍后定义的数组。大小是未知的,sizeof(array)
应该会产生一个错误。 - chqrlieint *array;
创建一个指针,其值是不确定的(它可以指向任何位置!)。
然后当你有了这个指针之后
array[9999] = 30;
int
值从array
所指向的位置设为30,但是因为你没有给array
一个实际的值,所以你不知道它所指向的位置在哪里。这就是未定义行为。区别在于当你使用int array[100]
时,会在堆栈上分配100 * sizeof(int)
的内存块;而当你使用int *array
时,需要动态分配内存(例如使用malloc
函数)来使用array
变量。动态分配的内存位于堆上,而非堆栈。
int array[100]
表示一个变量 array
,它将能够容纳100个int值,这个内存将从堆栈中分配。变量array
将具有数组的基本地址,并为其分配内存。int *array
的情况下,由于您将其声明为本地变量,指针变量array
将具有垃圾地址。因此,如果您执行array[9999]
,它可能会导致分段违规,因为您正在尝试访问程序外部的垃圾内存位置。array[9999]
不一定会导致段错误。这种行为在 C 标准中没有定义。该地址可能位于可访问内存内,或者代码可能会被优化以意想不到的方式转换。 - Eric Postpischil以下是一些你可能会发现有用的要点:
int arr[N]
,你可以指定一个类型为 int
的数组,它可以存储 N
个整数。要获取有关数组占用多少内存的信息,可以使用 sizeof
运算符。只需将数组中的项目数乘以类型的大小:N*sizeof(int)
。*arr
与 arr[0]
相同,你可能会想知道为什么 a[5] == 5[a]。int arr[] = {1, 2}
,则数组的大小由编译器计算,可以在运行时得知。int *array
,您可以指定类型为int
的指针array
int array[100];
定义了一个 int 数组。
int *array;
定义了一个指向 int
的指针。这个指针可以指向一个 int
变量,或者指向一个 int
数组的元素,也可能什么都不指向 (NULL
),甚至是指向内存中一个任意的、有效或无效的地址,这种情况发生在它是未初始化的局部变量的情况下。称这个指针为array
有点误导人,但通常用于命名函数参数,该参数确实指向实际的数组。编译器无法从指针值确定数组的大小(如果有)。
这里有一个地形隐喻:
把数组看作是一条街道,上面有建筑物。它有GPS坐标(内存地址),有名称(但不总是),以及固定数量的建筑物(在给定时间内难以更改)。街道名称和建筑物编号共同指定了一个精确的建筑物。如果您指定的数字大于最后一个数字,则是无效地址。
指针是一种非常不同的东西:将其视为地址标签。它是一张小纸片,可用于识别建筑物。如果它为空(空指针),则无用;如果您将其粘贴到信件上并发送该信件,则该信件将丢失和丢弃(未定义行为,但很容易判断其是否无效)。如果您在其上写入无效地址,则效果类似,但在交付失败之前可能会花费更多(未定义行为,并且难以进行测试)。
如果一条街道被夷平(如果内存被释放),则先前编写的地址标签不会被修改,但它们不再指向任何有用的内容(如果您发送该信件,则是未定义行为,这是一种困难的情况)。如果稍后使用标签上的名称命名新街道,则可能会传递该信件,但可能不会按预期方式传递(再次是未定义行为,因为内存已被释放,并且某些其他分配的对象恰好位于相同的内存地址)。
如果您将一个建筑物传递给函数,则通常不会挖掘它并运输它,而只需传递其街道地址(指向街道第n个建筑物的指针,&array[n]
)。如果您没有指定建筑物,只是命名了街道,则表示前往该街道的开头。同样,在C语言中将数组传递给函数时,函数接收到数组开头的指针,我们说数组退化为指针。
在int * array
中不指定大小,array[9999] = 30
可能会导致分段错误,因为它可能会导致访问不可访问的内存。
基本上,int * array
指向随机位置。要访问第9999个元素,array
必须指向具有足够空间的位置。但是语句int * array
没有明确为此创建任何空间。
int *array = malloc(sizeof(int)*10000)
。在这里,10000
就是数组的大小。如果您不让指针指向有效的内存空间,则array[9999]=30
是未定义的行为,并且很可能会导致程序崩溃或产生其他错误/不可预测的结果。 - Blazeint *array
必须手动进行 malloc() 分配。 - Shark