c语言中的数组和指针

来源:互联网 发布:mac os 10.6 dmg下载 编辑:程序博客网 时间:2024/05/16 14:24

    编译器在处理对数组的引用 如a[i] 在编译的时候总是被编译器改成*(a+i),其实方括号也是一个运算符,类似像加法运算一样,取下标操作数是可以互换的,因为在编译器处理*(a + i)和*(i+a)是一样的,也就说在

1、表达式中 指针和数组是可以互换的

2、下标运算符总是指针的偏移量相同

3、在函数参数的声明中,数组名被当做指向该数组的第一个元素的指针,

其他情况下 数组和指针是不一样的,如 数组  char a[ ] = "abcdefg";  和 char *p = “abcdefg”   

a 和&a中存的都数组的首地址

p存的一个指针的地址 *p的地址才是数组的首地址  也就是说用指针表示数组比直接表示数组多一次操作,相当于间接访问数组

取a[0]的过程是 首先得到a的地址 然后加上下标运算符的偏移量 得到结果 2步

取p[0]的过程是首先得到p的地址,然后取得*p的内容 数组a的首地址 然后在加上偏移量 多一次操作 3步

所以在声明和定义数组的时候要互相匹配 即 文件1定义一个char a[ ] = "bbbbbb",文件2声明的时候要声明为extern char a[]  不能写成 extern char  *a;然后在程序的某个地方 出现了 a[0]之类的引用 编译连接能够通过 但是运行的时候 程序就会挂掉 这种错误是很难发现的  ,另一方面在文件1中定义了char *a = "bbbb" 文件2中 上面了 extern  char a[ ];可以编译连接都通过 甚至运行的时候程序也不挂掉 但是取得的数据确实错的,所以还是建议 在声明的时候 最好和定义时候写法是一样的 


至于 文件1定义一个char a[ ] = "bbbbbb",文件2声明的时候要声明为extern char  *a ,并在文件2某一个地方 用a[0]使用数组元素的时候会出错的原因是 

文件2 声明a是一个指针 所以 编译器首先通过a的地址 取得a中存取数组的内容 ,然后把这个内容当做数组的地址 和偏移量进行偏移 来取得数组的元素,但是文件1中 a的定义是 

char a[ ] 所以 a中存放的就是数组的地址 这样编译器会取得一个字符 然后把这个字符当做地址和偏移量进行偏移操作 当然就出错了。。。 

另一方面 在文件1中定义了char *a = "bbbb" 文件2中 上面了 extern  char a[ ] ,在文件2某一个地方用a[0]使用数组元素的时候得到的数据也是错误的 原因是 在文件2中 a被声明为 char a[ ] ,编译器就把a当做数组来处理 ,文件1中实际上定义的是一个指针 ,编译器先取得a的内容 然后加上偏移量  实际上是在文件1定义的指针的地址上进行偏移取得的值 结果当然不对了

 其实只要记住 指针是通过三个步骤取得 数组的值  数组是通过两个步骤取得数据的值 所以在声明和定义的时候要一一对应才不会出错 特殊情况是 最开始说的三条中 数组被编译器转换成 指针来处理了 ,可能这样做编译器的效率会更高些,只用处理一种情况 而不用分开处理了 。


这种错误其实也类似于 一个文件中定义了一个浮点数 另一个文件中却把它声明为整形的 当然就出错啦!


附 测试

文件1

char *test = "bbbbbb";



文件2

#include <IOSTREAM>#include <CSTDIO>using namespace std;extern  char test[];int ga[10] = {1,2,3,4,5,6,7,8,9,0};void f1(int ca[]){printf("f1 : \n ca = %d \n &ca = %d \n &(ca[0]) = %d \n &(ca[1]) = %d \n",ca,&ca,&(ca[0]), &(ca[1]));}void f2(int *ca){printf("f2 : \n ca = %d \n &ca = %d \n &(ca[0]) = %d \n &(ca[1]) = %d \n",ca,&ca,&(ca[0]), &(ca[1]));}int main(){char a[10] = "abcdefg";int b[10] = {1,2,3,4,5,6,7,8,9,1};char *p = "abcd";char c[] = "bbbb";printf("p = %d \n *p = %d \n",p,*p);printf("&p = %d \n &(*p) = %d \n",&p,&(*p));printf("c = %d \n *c = %d \n",c,*c);printf("&c = %d \n &(*c) = %d \n",&c,&(*c));cout<<"a[2] = "<<a[2]<<endl;cout<<"2[a] = "<<2[a]<<endl;cout<<"main"<<endl;f1(b);f2(b);cout<<"global"<<endl;f1(ga);f2(ga);printf(" ga = %d\n &ga = %d \n &(ga[0]) = %d \n &(ga[1]) = %d\n",ga,&ga,&(ga[0]),&(ga[1]));cout<<"test[1] = "<<test[0]<<endl;return 0;}




0 0
原创粉丝点击