指针和数组是完全不同的东西。两者之间的任何相似和混淆都是 C 语言的产物。
指针是一个变量,它保存另一个变量的位置。数组(在 C 中)是相同类型的值的集合,在内存中连续分配。
数组通过算术访问指向基元素的指针,[0]
. 如果对引用数组的表达式求值,则出现的值是指向 element 的指针[0]
。
int array[10];
int *p = array; /* array expression yields pointer to array[0] */
int *q = &array[0]; /* q also points to same place as p */
C 中的数组表示法是一个假的,它实际上与指针一起工作。语法E1[E2]
的含义与*(E1 + E2)
(假设 E1 和 E2 有足够的括号,我们不必被关联性和优先级分心。)当我们通过 获取元素的地址时&E1[E2]
,这与&*(E1 + E2)
. 地址和取消引用“取消”离开E1 + E2
。因此,这些也是等价的:
int *r = array + 3;
int *q = &array[3];
因为array[i]
和pointer[i]
都是有效的语法,处于新手阶段的人(误认为语法是语义)得出的结论是数组和指针在某种程度上是同一回事。
花一些时间用汇编语言编程。在汇编语言中,您可能会定义一些像这样的存储:
A: DFS 42 ;; define 42 words, labelled as A.
然后像这样使用它:
MOV R13, A ;; address of A storage is moved into R13
MOV R1, [R13 + 3] ;; load fourth word, A[3]
R13 指向存储。这并不意味着 A是一个指针。A 是存储的名称。当然,要使用存储,我们需要它的有效地址,因此对 A 的引用可以解决这个问题。当代码被汇编和链接时,该MOV
指令最终会将一些数字地址加载到 R13 中。
C 只是一种高级汇编语言。数组就像命名存储,它解析为其有效地址(作为指针数据类型)。
数组并不总是解析到它们的有效地址。sizeof a
以字节为单位计算数组的大小a
,而sizeof p
计算指针数据类型的大小p
。
另一个区别是数组的名称不能引用该数组以外的任何地方,而我们可以为指针赋值:
array++; /* invalid */
array = &array[0]; /* invalid */
p = &array2[0]; /* valid */
p++; /* valid: point to the next element in array2 */