解引用指针和访问数组元素的区别 [英] Difference between dereferencing pointer and accessing array elements
问题描述
我记得有一个例子说明了指针和数组之间的区别.
I remember an example where the difference between pointers and arrays was demonstrated.
当作为函数参数传递时,数组衰减为指向数组中第一个元素的指针,但它们并不等效,如下所示:
An array decays to a pointer to the first element in an array when passed as a function parameter, but they are not equivalent, as demonstrated next:
//file file1.c
int a[2] = {800, 801};
int b[2] = {100, 101};
//file file2.c
extern int a[2];
// here b is declared as pointer,
// although the external unit defines it as an array
extern int *b;
int main() {
int x1, x2;
x1 = a[1]; // ok
x2 = b[1]; // crash at runtime
return 0;
}
链接器不对外部变量进行类型检查,因此在编译时不会产生错误.问题是 b
实际上是一个数组,但是编译单元 file2
不知道这一点,而是将 b
当作一个指针,导致尝试取消引用时崩溃.
The linker does not type-check for external variables so no errors are generated at compile time. The problem is that b
is in fact an array, but the compilation unit file2
is unaware of that and treats b
as a pointer, resulting in a crash when trying to dereference it.
我记得有人解释过,这很有道理,但现在我不记得解释了,也无法自己想出来.
I remember when this was explained it made perfect sense, but now I can't remember the explanation nor I can come up to it on my own.
所以我想问题是在访问元素时数组与指针的处理方式有何不同?(因为我认为 p[1]
被转换为(等价于)*(p + 1)
,无论 p
是否是一个数组或指针——我显然错了).
So I guess the question is how is an array treated differently than a pointer when accessing elements? (because I thought that p[1]
is converted to (the assembly equivalent of) *(p + 1)
regardless if p
is an array or a pointer — I am obviously wrong).
两个解引用生成的程序集(VS 2013):
注意: 1158000h
和1158008h
分别是a
和b
的内存地址
The assembly generated by the two dereferences (VS 2013):
note: 1158000h
and 1158008h
are the memory addresses of a
and b
respectively
12: x1 = a[1];
0115139E mov eax,4
011513A3 shl eax,0
011513A6 mov ecx,dword ptr [eax+1158000h]
011513AC mov dword ptr [x1],ecx
13: x2 = b[1];
011513AF mov eax,4
011513B4 shl eax,0
011513B7 mov ecx,dword ptr ds:[1158008h]
011513BD mov edx,dword ptr [ecx+eax]
011513C0 mov dword ptr [x2],edx
推荐答案
Thanks to the link provided by @tesseract in the comments: Expert C Programming: Deep C Secrets (page 96), I came up with a simple answer (a simple dumb down version of the explanation in the book; for a full academic answer read the book):
- 在声明
int a[2]
时:- 编译器为
a
提供了一个存储该变量的地址.这个地址也是数组的地址,因为变量的类型是数组. - 访问
a[1]
意味着:- 检索该地址,
- 添加偏移量和
- 在这个计算出的新地址访问内存.
- when declared
int a[2]
:- the compiler has for
a
an address where this variable is stored. This address is also the address of the array since the type of the variable is array. - Accessing
a[1]
means:- retrieving that address,
- adding the offset and
- accessing the memory at this computed new address.
- 编译器也有
b
的地址,但这是指针变量的地址,而不是数组. - 所以访问
b[1]
意味着:- 检索该地址,
- 访问该位置以获取
b
的值,即数组的地址 - 向该地址添加偏移量,然后
- 访问最终内存位置.
- the compiler also has an address for
b
but this is the address of the pointer variable, not the array. - So accessing
b[1]
means:- retrieving that address,
- accessing that location to get the value of
b
, i.e. the address of the array - adding an offset to this address and then
- accessing the final memory location.
这篇关于解引用指针和访问数组元素的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- the compiler has for
- 编译器为