Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141110
  • 博文数量: 25
  • 博客积分: 100
  • 博客等级: 中士
  • 技术积分: 310
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-03 18:56
文章分类

全部博文(25)

文章存档

2012年(4)

2011年(21)

分类: C/C++

2011-06-20 23:10:14

数组与指针到底是啥关系啊?引用《C语言深度剖析》中的一句话:“他们没有任何关系,只是经常穿着相似的衣服逗你玩儿罢了”。
数组与指针的相互转换是非常微妙且容易出错的:
1.数组符号的值以及其取址的值都是数组地址,但又不完全相同(主要是用sizeof以及地址+1操作时,详见“类型和类型转换一节”);
2.数组在参数传递时自动变成指针。
3.数组的访问方式a[n],最终都转换成*(a+n)
这几点内容在很多书上都有详述,而我这一节详细分析一下数组与变量的定义与声明时的一致性问题,我们将看到不一致的定义将引起灾难。

代码:
array1.c
  1. #include <stdio.h>
  2. char apple[] = "apple";
  3. char banana[] = "banana";
  4. char *cherry = "cherry";
  5. char *peach = "peach";


  6. func(){

  7.     puts("orginal definition");
  8.     printf("the address of apple is %x\n",(int)&apple);
  9.     printf("the value of apple is %x\n",(int)apple);
  10.     printf("the value of apple[0] is %x\n",(int)apple[0]);
  11.     puts("*******************************************");
  12.     printf("the address of banana is %x\n",(int)&banana);
  13.     printf("the value of banana is %x\n",(int)banana);
  14.     printf("the value of banana[0] is %x\n",(int)banana[0]);
  15.     puts("*******************************************");
  16.     printf("the address of cherry is %x\n",(int)&cherry);
  17.     printf("the value of cherry is %x\n",(int)cherry);
  18.     printf("the value of cherry[0] is %x\n",(int)cherry[0]);
  19.     puts("*******************************************");
  20.     printf("the address of peach is %x\n",(int)&peach[0]);
  21.     printf("the value of peach is %x\n",(int)peach);
  22.     printf("the value of peach[0] is %x\n",(int)peach[0]);
  23. }
array2.c
  1. #include <stdio.h>
  2. extern func();
  3. extern char *apple;//from char[] to char *
  4. extern char banana[];//from char[] to char[]
  5. extern char *cherry;//from char * to char *
  6. extern char peach[];//from char* to char[]

  7. main(){
  8.     func();
  9.     puts("external declaration");
  10.     printf("the address of apple is %x\n",(int)&apple);
  11.     printf("the value of apple is %x\n",(int)apple);
  12.     //printf("the value of apple[0] is %d\n",(int)apple[0]);//会引起段错误
  13.     puts("*******************************************");
  14.     printf("the address of banana is %x\n",(int)&banana);
  15.     printf("the value of banana is %x\n",(int)banana);
  16.     printf("the value of banana[0] is %x\n",(int)banana[0]);
  17.     puts("*******************************************");
  18.     printf("the address of cherry is %x\n",(int)&cherry);
  19.     printf("the value of cherry is %x\n",(int)cherry);
  20.     printf("the value of cherry[0] is %x\n",(int)cherry[0]);
  21.     puts("*******************************************");
  22.     printf("the address of peach is %x\n",(int)&peach);
  23.     printf("the value of peach is %x\n",(int)peach);
  24.     printf("the value of peach[0] is %x\n",(int)peach[0]);
  25.     puts("*******************************************");

  26. }
输出结果:
  1. orginal definition
  2. the address of apple is 804a018
  3. the value of apple is 804a018
  4. the value of apple[0] is 61
  5. *******************************************
  6. the address of banana is 804a01e
  7. the value of banana is 804a01e
  8. the value of banana[0] is 62 
  9. *******************************************
  10. the address of cherry is 804a028
  11. the value of cherry is 80488e8
  12. the value of cherry[0] is 63 
  13. *******************************************
  14. the address of peach is 804a02c
  15. the value of peach is 80488ef
  16. the value of peach[0] is 70 

  17. external declaration
  18. the address of apple is 804a018
  19. the value of apple is 6c707061 就是'a' 'p' 'p' 'l'
  20. 错误 会引起段错误
  21. *******************************************
  22. the address of banana is 804a01e
  23. the value of banana is 804a01e
  24. the value of banana[0] is 62  正确
  25. *******************************************
  26. the address of cherry is 804a028
  27. the value of cherry is 80488e8
  28. the value of cherry[0] is 63 正确
  29. *******************************************
  30. the address of peach is 804a02c
  31. the value of peach is 804a02c
  32. the value of peach[0] is ffffffef 错误
  33. *******************************************
这里的代码试验了定义为指针或数组,而以指针或数组的方式访问的四种可能组合情况,并打印出各符号的地址与值。首先,可以肯定以一致的方式定义与引用不会产生错误;其次另外两种定义与引用不一致的情况会引起错误。
首先明确一点,作为全局符号表,其中存储的都是全局符号的地址,而不是它们的值。
1.定义为数组,按照指针引用的情况:例如apple[0],过程就是在全局符号表里面取apple这个标号的地址,该地址对应的值,此时该值被理解为一个指针,也就是4个字节,因此取出来的也就是数组的前4个元素appl;故而apple[0]的地址也就是0x6c707061,访问这个地址当然会引起段错误。总结一下,这种情况下出错主要是由于apple作为数组时其标号值就是标号地址这一歧义引起的。
2.定义为指针,按照数组方式引用的情况:在全局符号表里面得到peach的地址0x804a02c,同样由于数组标号的值即为地址,peach数组的地址出现了错误。其真实地址应该是peach的地址处对应的那个指针值,也就是0x804a02c处存储的值0x80488efc。现在peach[0]相当于访问了0x804a02c处的数值。也就是0xef,按照整数打印时判断为负数,所以前面填充了很多ffffff.
至此,一切真相大白,世界人民震惊了。。。。。一个小小的数组和指针竟能引发出如此大的混乱,这不得不引起我们的反思。。。。
PS.参考《C专家编程第4章》
阅读(1530) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~