解引用指针和访问数组元素的区别 [英] Difference between dereferencing pointer and accessing array elements

查看:33
本文介绍了解引用指针和访问数组元素的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我记得有一个例子说明了指针和数组之间的区别.

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):
注意: 1158000h1158008h分别是ab的内存地址

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  

推荐答案

感谢@tesseract 在评论中提供的链接:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆