一、问题
对于表达式int b[4],请问,变量b[0]是什么类型,变量b又是什么类型?
二、答案
b[0]表示数组b的第1个值,b[0]的类型是整型。变量b又是什么类型?一个合乎逻辑的答案是它表示整个数组,但事实并非如此。在C中,在几乎所有使用数组名的表达式中,数组名的值是一个指针常量,也就是数组第1个元素的地址。它的类型取决于数组元素的类型:如果它们是int类型,那么数组名的类型就是“指向int的指针常量”;如果它们是其他类型,那么数组名的类型就是“指向其他类型的指针常量"。
请不要根据这个事实得出数组和指针是相同的结论。数组具有一些和指针完全不同的特征。例如,数组具有确定数量的元素,而指针只是一个标量值。编译器用数组名来记住这些属性。只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量
三、原理
指针和数组并不是相等的。为了说明这个概念,请考虑下面这两个声明
int a[5];
int *b;
a和b能够互换使用吗?它们都具有指针值,它们都可以进行间接访问和下标引用操作。但是它们还是存在相当大的区别。
声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值是一个常量,指向这段空间的起始位置。
声明一个指针变量时,编译器只为指针本身保留内存空间,它并不为任何整型值分配内存空间。而且,指针变量并未被初始化为指向任何现有的存空间,如果它是一个自动变量,它甚至根本不会被初始化。把这两个声明用图的方法来表示,你可以发现它们之间存在显著不同。
因此,上述声明之后,表达式*a是完全合法的,但表达式*b却是非法的。*b将访问内存中某个不确定的位置,或者导致程序终止。另一方面,表达式b++可以通过编译,但a++却不行,因为a的值是个指针常量 。
int a[5];
int b[5];
int *c = a;
int *c = b;//正确
b = a;//错误
int *c=a;
这条赋值语句说明了为什么理解表达式中的数组名的真正含义是非常重要的。如果数组名表示整个数组,这条语句就表示整个数组被复制到一个新的数组。但事实上完全不是这样,实际被赋值的是一个指针的拷贝,c所指向的是数组的第1个元素。
因此,像下面这样的表达式是非法的。
b=a;
你不能使用赋值符把一个数组的所有元素复制到另一个数组。你必须使用一个循环,每次复制一个元素。
考虑下面这条语句
a=c;
c被声明为一个指针变量,这条语句看上去像是执行某种形式的指针赋值,把c的值复制给a。但这个赋值是非法的:记住!!在这个表达式中,a的值是个常量,不能被修改。
参考: