int array[100];
int *array;
所以我对int array[100]
与int * array
之间的差异感到困惑。
当我执行int array[100]
时很重要(100
只是int
的一个示例),我只是在内存中保留了100个整数,但是我可以执行int * array
并且我没有为该数组指定任何类型的大小,但是我仍然可以进行array[9999] = 30
,这仍然有意义。
那么这两者之间有什么区别?
答案 0 :(得分:5)
指针是一个 pointer ,它指向其他地方(如数组的第一个元素)。编译器没有关于它可能指向的位置或它可能指向的数据大小的任何信息。
一个数组是由多个相同类型的连续元素组成的数组。编译器知道它的大小,它总是指定大小(尽管有时大小是隐式指定的)。
可以初始化数组,但不能分配给它。数组也经常衰减到指向其第一个元素的指针。
数组衰减示例:
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
。
所有这些信息以及更多信息,都应该放在任何好书,教程或课堂中。
答案 1 :(得分:2)
不同之处在于,执行int array[100]
时,在{em> stack 中分配了100 * sizeof(int)
的存储块,但是执行int *array
时,需要动态分配内存(例如,使用malloc
函数)以使用array
变量。动态分配的内存位于堆上,而不是 stack 上。
答案 2 :(得分:2)
int array[100]
表示变量array
,该变量将能够容纳100个int值,此内存将从堆栈中分配。变量array
将具有数组的基地址,并且将为其分配内存。
但是对于int *array
,由于您将其声明为局部变量,因此指针变量array
将具有垃圾地址。因此,如果您尝试array[9999]
,则可能会导致分段冲突,因为您正在尝试访问程序外部的垃圾内存位置。
答案 3 :(得分:1)
非技术性解释:
指针的内容引用一个地址(可能有效或无效)。数组具有地址(该地址必须有效才能使该数组存在)。
您可以认为指针就像信封一样-可以在上面放置任何想要的地址,但是如果要将其发送到特定的地方,则该地址必须正确。
一个数组就像你的房子-它存在于某个地方,所以它有一个地址。正确解决的问题会被发送到那里。
简而言之:
指针持有一个地址。
一个数组具有一个地址。
所以
int *array;
创建一个不确定值的指针 (它可以指向任何地方!)。
当你拥有
array[9999] = 30;
您正在尝试将第int
指向的第9999个array
值设置为30的值。但是您不知道array
的位置点,因为您没有提供实际值。
那是未定义的行为。
答案 4 :(得分:1)
在int * array
中未指定大小,array[9999] = 30
可能会导致分段错误,因为这可能会导致无法访问的内存的访问
答案 5 :(得分:1)
一些有用的知识点:
int arr[N]
,您可以指定类型为int
的一个数组,该数组可以存储N
整数。要获取有关占用多少内存阵列的信息,可以使用sizeof
运算符。只需将数组中的项目数乘以类型N*sizeof(int)
的大小即可。*arr
与arr[0]
相同,您可能还会想知道为什么a[5] == 5[a]。int arr[] = {1, 2}
,则数组的大小可能在运行时已知。int *array
,您可以指定类型为array
的指针 int
答案 6 :(得分:0)
int array[100];
定义了int
的数组。
int *array;
为int
定义了一个指针。该指针可能指向int
变量或int
数组的元素,或者根本没有指向(NULL
),甚至指向其中的任意,有效或无效地址。内存,当它是未初始化的局部变量时就是这种情况。调用此指针array
有点误导,但在命名确实指向实际数组的函数参数时经常使用。编译器无法根据指针值确定数组的大小。
这是一个地形隐喻:
将数组想像成具有建筑物的街道。它具有GPS坐标(内存地址),名称(但不总是)和固定数量的建筑物(在给定时间很难更改)。街道名称和建筑物编号一起指定了精确的建筑物。如果您指定的数字大于最后一个数字,则该地址无效。
指针是完全不同的东西:将其视为地址标签。这是一张小纸,可以用来识别建筑物。如果为空(空指针),则无用,如果将其粘贴到字母上并发送,则字母将丢失并被丢弃(行为不确定,但很容易看出它是无效的)。如果您在上面写了一个无效的地址,则效果是相似的,但是在交付失败之前(未定义的行为且难以测试)可能会花费更多。
如果街道被夷为平地(如果释放了内存),则先前编写的地址标签不会被修改,但是它们将不再指向任何有用的内容(如果发送信件,则行为不确定,这是困难的一种)。如果以后用标签上的名称命名了一条新街道,则可能会发送该字母,但可能不符合预期(再次发生未定义的行为,释放了内存,而其他分配的对象恰好位于相同的内存地址)。
如果您将建筑物传递给功能,通常不会发掘并运输它,而只是传递其街道地址(指向街道第n座建筑物的指针) ,&array[n]
)。如果您未指定建筑物,而只是命名街道,则意味着转到街道的起点。同样,当将数组传递给函数为C时,函数会收到指向数组开头的指针,我们说 arrays会随着指针的衰变。