在C语言的声明里面,有时候在一个文件中声明了char *p;却在另外一个文件里面用extern char p[];来引用,或者在一个文件中声明了char arry[100];却在另外一个文件中用char *arry;来引用。这样乍看起来好像没事,实则是在挖坑,解析如下:(简化了在一个程序里面做实验)
定义为数组却声明为指针:
#include<stdio.h> int main() { char arry[10]; strcpy( arry , "abcdef" ); char **p; p = &arry; printf("&arry = %p p = %x\n",&arry,*p); //**p就是取地址0x64636261的值了,系统不允许 return 0; }
运行结果为:
&arry = 0022FF30 *p = 64636261
注意后面的那个*p的地址,恰好是abcd的asc码值。
2.定义为指针却声明为数组:
#include<stdio.h> int main() { char *p; char arry[100]; int i = 0; strcpy( arry , "abcdef" ); p = arry; printf("p = %p\n",p); for( i = 0 ; i < 7 ; i++ ) { printf("p[%d] = %x\n",i,p[i]); } return 0; }
运行结果为:
p = 0022FEC0 p[0] = 64636261 p[1] = 6665 p[2] = 0 p[3] = 763298da p[4] = 2116ab91 p[5] = 0 p[6] = 0
注意p[0],p[1].,恰好是字符'abcdef'的asc值。
解释:
首先明白指针和数组的取值的不同,对于指针,取值分为三步,例如char *p="abc",p的地址是4624,p的值是5081(即p指向的地址,也就是abc保存的内存的首地址):
知道指针p的内容,也就是'4624'。
取p的值,即指向的内容,也就是'5081'。
取地址5081的内容,也就是abc。
对于数组,取值分为两步,例如char arry[10];strcpy( arry,"abcd" );
知道arry的地址,假设是4624.
取地址(4624+i)的值(或者说是取4624指向的地址存储的值),也就是abcd。
弄清上面的概念了,然后看第一种情况,定义为数组却声明为指针,一步步来,第一步都是知道变量的地址,第二步第二步应该取变量地址指向的地址存储的值,但是去变成了去变量地址指向的地址,也就是把存储的值当做地址了,然后再取这个地址指向的值。所以出现那种情况。
第二种情况,定义为指针却声明为数组,按照同样的道理,第一步都是取变量的地址,第二步应该去变量地址指向的值作为新的地址,却变成了取变量的地址的值,也就是把地址当做数组里面的数据来读取了,所以出现上面的情况。