数组定义却以指针形式访问

2771阅读 0评论2011-05-03 zhangliangfnst
分类:C/C++

设想这样一种情况:
在file1.c中定义如下数组:
  1. char str[10] = {1,2,3,4,5,6,7,8,9,10};

而在另一个文件file2.c中想要引用此数组数据却如此声明:

  1. extern char *str;

这样的错误及其常见。如果运行含有此代码的程序,一般会segment fault。这也是最好的结果。经过后面的说明后,你会理解为什么说这样是最好的结果。

想要弄明白这个问题的根源,需要理解数组和指针的访问方式区别。

在定义一个数组后,我们可以通过str[2];来访问其中的元素;

而定义一个指针后,我们也可以通过str[2];来访问其中的元素,但是访问的方式却是大相径庭的。

了解了上述的访问方式的区别后,我们看一下

char str[10] = {1,2,3,4,5,6,7,8,9,10};

extern char *str;

由于我们认为在file2.c中指定str是一个外部指针,那么编译器就会以访问“指针所指向的元素的方式”访问元素。同时我们也知道,str这种符号的地址是在编译时期就确定的。而此时这个符号的地址正好是str数组的第0个元素的地址(即str[0]的地址)。所以在file2.c中访问str[1]时,会先找到str符号的地址取其内容再加上1然后解引用。就是要访问的元素。

而此时,数组符号地址对应的内容为1(str[0])--->0x00000001 + 4(bytes)去访问这个地址的内容,当然会segment fault了。

我们可以做一个实验,把str[0]内存单元的内容填写为一个变量的地址 - 1 然后去利用指针去访问。

file1.c

  1. #include<stdio.h>
  2. int p = 9999;
  3. int str[10] = {&p - 1,2,3,4,5,6};

file2.c

  1. #include<stdio.h>
  2. extern int *str;
  3. int main()
  4. {
  5.         int a = str[1];
  6.         printf("%d\n",a);
  7.         return 0;
  8. }
通过这段代码应该很好理解上述问题的原因了。究其根本:就是由于访问方式的不同所造成的。
上一篇:__user && address_space(1)(转载)
下一篇:素数的妙用---一道关于字符串的面试题