首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

数组跟指针的区别,数组和其他类型都有区别

2012-07-31 
数组和指针的区别,数组和其他类型都有区别.一直认为,对C的指针比较了解了.最近突然发现一种写法,在C陷阱和

数组和指针的区别,数组和其他类型都有区别.
一直认为,对C的指针比较了解了.最近突然发现一种写法,在C陷阱和缺陷36页左右.
  char a[9]="abcdefgh";
  *(a+1) 的值就是'b';
  我忽然记得看C专家编程的时候,认为数组和指针完全不一样,之所以混淆主要就是因为子函数传值的时候。于是又重新看了下C专家编程,84页左右,发现自己其实当时并没有理解真正的意思.
  a声明是数组,a的地址是在编译的时候确定的.现在假如a在编译器符号表具有一个地址为9980.
  运行时第一步: 取i的值,与 9980相加.(char型就是1*i);
  运行时第二步: 取地址(9980+i)的内容.
  所以, a[1]的值就是 a的地址9980 + 1中的内容 'b';
  现在再声明一个char *p="abcdefgh";如果用p[i]这种写法来取值.
  首先,p在编译器符号表具有一个地址 4624.
  运行时第一步: 取4624的地址的内容,假设为5650;
  运行时第二步: 取i的值,和5650相加.
  运行时第三部: 取地址(5650+i)的内容.
  所以,p[1]的值就是 *(*(&p)+1)=*(p+1)的值,为'b'.

  关键的地方就在于, a是数组,p是指针.然而 a[1]的值和p[1]的值相同,也就是*(a+1)的值和*(p+1)的值相同.非常容易造成指针和数组相同的假象.但是,明显他们的取值方式是不一样的,是的,这就是造成这种假象的原因.

  结论: 在C语言中,数组类型是不同于其他类型的,当它在运行的时候,取的是它在符号表中得地址, 而int,float,*这种,会取符号表中得地址,进而地址中得值.
  
  在C语言中,之所以数组名称a是 不可修改的左值,就是因为a代表的是符号表中得地址,是在编译的时候就确定的.
   
  了解了这个,再回头看子函数传值的时候.
  int sub_func( char * str)
  {
  取 str[1]的值;
  } 函数定义.
  传值的时候 ret = sub_func( a);
  下面来分析下,在sub_func定义的时候,str在符号表中,地址为4210. 当调用函数的时候,将4210地址的值取出来,然后将数组a在符号表地址为9980传给4210地址中,作为4210地址的内容.这样,传值过程就算结束.在取str[1]的时候,就是如同上面*p的取值一样。
   
  上面说的符号表地址等,其实是不对的,因为程序只有在运行的时候才在内存中有地址。"每个符号的地址在编译的时候是可知的。"个人猜测是符号表加载进内存的相对地址是固定的。这不是本问题的关键地方,不严谨的地方请包涵.

  第一次发帖,如果有不对的地方,大家多多批评,发上来一是分享下自己的理解,二是让大家发现自己的不足.

[解决办法]
从很多实现上来看,访问一个变量,实际是先找到变量的地址,然后在读取变量地址里的数据的。
而访问数组元素,直接是数组首地址+offset,具体可以反汇编看一下,这一点正如楼主所说的.
而更深层次的区别,请参考:
http://blog.csdn.net/supermegaboy/article/details/4855027
[解决办法]
数组名不是左值,数组取下标操作的结果,比如a[1],才是左值。当然,*(a + 1)这样的也是左值。
如果不是全局变量,数组名未必放进符号表,符号表在很大程度上是给链接器和加载器使用的。一个局部的数组名,即使放进符号表,通常也只是用于调试的符号。
[解决办法]

探讨

编译器符号表 是什么概念?

[解决办法]
楼主理解有误,
“运行时第一步: 取4624的地址的内容,假设为5650”
这是编译器确定的,不需要运行时确定。

热点排行