c语言中的数组和指针

12 篇文章 0 订阅

    编译器在处理对数组的引用 如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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值