一、一维数组
1.1 数组名
下面这些声明:
int a;
int b[10];
我们把变量a 称为标量,因为它是个单一的值,这个变量的类型是一个整数。我们把变量b称为数组,因为它是一些值的集合。下标和数组名一起使用
用于标识该集合某个确定的值。
问题:b[4]的类型是整型,但b的类型又是什么?它所表示的又是什么?
一个合理逻辑的作案是它表示整个数组,但事实并非如此。在C中,在所有使用数组名表达式中,数组名的值是一个指针常量。
也就是数组第1个元素的地址。它的类型取决于数组元素的类型:如果它们是整型,那数组名的类型就是“指向int型的常量指针”
注意:这个值是指针常量,而不是变量。你不能改常量的值。因为数组在内存的存储位置是固定的。不能在程序中修改。
只有在两种场合下,数组名并不用指针常量来表——就是数组名作为sizeof()操作符或单目操作符&的操作数。sizeof返回整个数组
的长度,而不是指向数组的指针的长度。取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量值的指针了。
如[例] int a[10];
int b[10];
int *c;……
c = &a[0];
表达式&a[0]是一个指向数组第1元素的指针。但那正是数组名本身的值,所以下面这条赋值语句和上面那条赋值语句所执行的是完全一样的:
c = a;
这条赋值语句说明了为什么理解表达式的数组名的真正含义是非常重要的。如果数组名表示整个数组,这条语句就表示整个数组被复制
到一个新的数组。但事实上完全不是这样,实际被赋值的是一个指针的拷贝,c所指向的是数组的第1个元素。因此,像下面的表达式:
b=a:
是非法的。你不能使用赋值符把一个数组的所有元素复制到另一个数组。你必须使用一个循环。第次复制一个元素。考虑下面这条语句
a=c;
c被声明为一个指针变量,这语句看上去像是执行某种形式的指针赋值,把c的值复制给a 但这个赋值是非法的:
记住!在这个表达式, a的值是个常量,不能被修改。
1.2 下标引用
在前面声明的上下文环境中,下面这个表达式是什么意思?
*[ b + 3]
它所指向的是数组第1个元素向后移3个整数长度的位置。然后,间接访问操作访问这个新位置。
我们现在来理解这句话:除了优先级之外,下标引用和间接访问完全相同。例如,下面这两个表达式是等同的。
array[sub]
*(array * (sub))
这里有个小例子,可以说明这种相等性
int array[10];
int *ap = array + 2;
记住,在进行指针加法运算时会对2进行调整。运算结果所产生的指针ap指向array[2]。
在下面各个涉及ap的表达式中,看看你能不能写出使用array的对等表达式。
ap 这个很容易,你只要阅读它的初始化表达式就能得到答案:array+2。另外,&array[2]也是与它对等的表达式。
*ap 这个也很容易,间接访问跟随指针访问它所指向的位置,也就是array[2]。你也可以写成:*(array+2).
ap[0] “你不能这么做,ap不是一个数组!”
ap+6 如果ap指向array[2],这个加法运算产生的指针元素是array[2]向后移6个整数位置的元素。
ap[6]与*(ap+6) 是等同的
1.3 指针与下标
指针有时会比下标更有效率。