首页 > 代码库 > C语言其实不简单:数组与指针
C语言其实不简单:数组与指针
之前在写C的时候,没怎么留意数组,就这么定义一个,然后颠来倒去的使用就行了。不过后来碰到了点问题,解决后决定写这么一篇博客,数组离不开指针,索性就放一起好了。
现在我定义了一个数组:int cc[10];
围绕这个数组有好几种指针:cc, cc+1, &cc[0], &cc, &cc+1等等。你知道它们都是什么含义吗?试试运行以下带代码:
#include <stdio.h>int main(){ int cc[10]; printf("%x\n", cc); printf("%x\n", cc+1); printf("%x\n", &cc[0]); printf("%x\n", &cc); printf("%x\n", &cc+1); getchar(); return 0;}cc,这是学数组时第一个接触的"指针",最为熟悉,它是数组的首个元素。
cc+1,这是指向数字第二个位置的指针。
&cc[0],这个其实就是cc,指向数组的首个元素。
&cc,这是什么玩意儿?指向指针的指针?
&cc+1,如果上面的意思是指向指针的指针,那这个岂不是指向野地址了?
假设运行环境是32位机,并且数组首地址为0x28ff00,那么:
cc的结果为0x28ff00,这点毫无疑问。
cc+1的地址是0x28ff04而不是0x28ff01,因为一个int占用了4个字节的空间。cc+1其实是当成cc+1*sizeof(int)来看待。
&cc[0]的结果是0x28ff00,cc[0]表示的是数组的首个元素,那么&cc[0]自然就是首个元素的地址了。&cc[0] == cc。
&cc,这个就难说了,指针cc的值是0x28ff00,&cc表示这个指针本身的地址,我们怎么可能会知道这个地址?输出是个随机地址吗?随机数的话这个输出完全没有意义啊。如果不是随机地址的话,难不成还是0x28ff00?这样的话a不就等于&a了?明显不对吧。。。
对于基本类型的指针,如int *tt; 那么*tt是其值,&tt是指针的地址,&tt != tt
但是上述的cc是个数组,实际上,&cc被编译成了&cc[0],但是其含义不同,&cc指向的是整个数组的开头。&cc与cc的指向可以用下图来形象表示:
上图可以看出,&cc其实代表的是int(*)[10],那么&cc+1就可以理解为cc + sizeof(cc)/4,之所以除以4是因为int型指针++其实是移动了4个字节。
又或者说%cc == cc + sizeof(cc)/4 == cc + 10,所以&cc+1的值为0x28ff28。
可见我们平常使用的数组名,并不能单纯的当成指针看待。数组名的本质是代表数组对象的变量名,是一个左值,是一个不能被改变的左值。但是由于在程序中不保存数组的大小,所以通过数组名只能访问数组的左值,不能访问数组的右值。由于这个原因,数组名在作为右值使用的时候被赋予另外一个新的意义——指向数组第一个元素的指针,这就是array-to-pointer转换规则。根据标准规定,只有当数组名作为sizeof、&运算符的操作数的时候,它是一个左值,其类型为数组类型。除此之外的所有情况,数组名都是一个右值,被编译器自动转换为指针类型,这种情况下我们就说数组名是一个指针,并且是一个指针常量。
接下来是另外一些有趣的东西,我们结合sizeof与数组输出各类值。以下程序的输出结果是什么?建议思考后再运行程序来验证答案。
#include <stdio.h> int main() { int cc[10]; printf("%d\n", sizeof(cc[0])); printf("%d\n", sizeof(cc)); printf("%d\n", sizeof(&cc)); printf("%d\n", sizeof(int(*)[10])); getchar(); return 0; }sizeof(cc[0]),一个int的大小,输出4,没问题。
sizeof(cc),注意不要和上面搞混,这不是数组首地址的指针,cc在这里是左值,其为数组类型,所以结果为40。
sizeof(&cc),这个的答案应该是多少呢?注意了,cc在这里还是左值,其为数组类型,但&cc不同于cc,不管数组怎么复杂它始终是个指针,32位机上指针大小始终是4个字节,所以结果为4。
sizeof(int(*)[10]),这个其实和上面的&cc是一个样的,代表了整个数组,但还是指针,所以结果同样为4。
练习:下面的程序输出结果是什么(假设32位机):
#include <stdio.h> int main() { int *p[2]; printf("%d\n", *p); printf("%d\n", sizeof(p)); printf("%d\n", sizeof(&p)); getchar(); return 0; }
答案是:随机数、8、4
再来一个练习:下列程序的输出是什么?
#include <stdio.h> int main() { char str[]="hactrox"; char *p = str; printf("%d %d\n", sizeof(str), sizeof(p)); getchar(); return 0; }
答案:8、4(不要忘了‘\0‘)