越简单越好:数组名和指针的区别
我相信很多人都跟我一样被某些书害的不浅,在C语言中一直还把指针跟数组名混为一谈。其实它们跟本就是两样的东西,指针就是指针,数组就是数组,网上也有很多大牛作过很多非常深入的讨论,但是个人感觉有时候把问题想得太复杂了反而不好,尤其是对于新手,因为我们新手很难搞懂编译器背着我们到底都干了些什么。我们有时候应该透过现象看本质,但有时候也不要太钻牛角尖,一口吃不出个胖子,必要时“难得糊涂”,站在抽象的角度去看事情,很多所谓的“本质”归根到底就是“规则”,让我们返朴归真看看标准是怎么说的,对于新手关于数组和指针的区别和以及什么时候“相同”只要记住《c专家编程》中提到的三个标准和三个例外就可以了:
规则1."表达式中的数组名被编译器当作一个指向该数组第一个元素的指针。"
规则2."下标总是与指针的偏移量相同。
规则3."在函数参数的声明中,数组名被编译器当作指向该数组的第一个元素的指针。"
在下列的情况下,对数组的引用不能用指向该数组第一个元素的指针来代替:
例外1.数组作为sizeof()的操作数,显然此时需要的是整个数组的大小,而不是所指向第一个元素的大小
例外2.使用&操作符取数组的地址
例外3.数组是一个字符串常量初始化值
一个很简单的例子:
#include <stdio.h> char ga[]="abcdrfghik"; void method(char ca[])//or char *ca { printf(" addr of arrary param = %#x \n",&ca); //规则3 printf(" (*ca) = %c \n",*ca); printf(" addr (ca[0]) = %#x \n",&(ca[0])); printf(" addr (ca[1]) = %#x \n",&(ca[1])); printf("++ca = %#x \n\n",++ca); } int main(void) { //例外2 这个只是数组和指针能够互换的一个例外。这里ga代表数组,这个获取的数组的地址 printf(" addr of arrary param = %#x \n",&ga); //规则1 printf(" (*ga) = %c \n",*ga); printf(" addr (ga[0]) = %#x \n",&(ga[0])); printf(" addr (ga[1]) = %#x \n",&(ga[1])); //例外1 printf(" sizeof ga = %d \n\n",sizeof(ga)); method(ga); return 0; }
另外,
“数组名被改写成一个指针的参数”规则并不是递归定义的。数组的数组会被改写成“数组的指针”而不是“指针的指针”
比如char c[8][10]所被改写对应的形参为 char (*)[10],为“数组的指针”。
一个简单的例子:
#include <stdio.h> #include <malloc.h> method(int a[3][2]) { int i=0; int j=0; for(i=0;i<=2;i++) { for(j=0;j<=1;j++) { printf("%d\n",a[i][j]); } } for(i=0;i<=2;i++) { for(j=0;j<=1;j++) { printf("%d\n",*(*(a+i)+j)); } } int k=0; for(k=0;k<=5;k++) { //a是指向 int (*)[2] 的行指针,*a即为二位数组的首行首元素的地址 printf("%d\n",*(*a+k)); } } int main(void) { int a[3][2]={{1,2},{3,4},{5,6}}; method(a); return 0; }
至于更深层的知识水到自然渠成。
作者:zhanjindong
出处:http://www.cnblogs.com/zhanjindong
个人博客:http://zhanjindong.com
关于:一个程序员而已
说明:目前的技术水平有限,博客定位于学习心得和总结。
出处:http://www.cnblogs.com/zhanjindong
个人博客:http://zhanjindong.com
关于:一个程序员而已
说明:目前的技术水平有限,博客定位于学习心得和总结。