《C和指针》对于数组这一节的总结,感觉总结的很精炼,多读有益!

在绝大多数表达式中,数组名的值是指向数组第一个元素的指针。这个规则只有两个例外: sizeof返回整个数组所占用的字节而不是一个指针所占用的字节。单目操作符&返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。(斟酌)


除了优先级不同之外,下标表达式 array[ value ] 和间接访问表达式 *(array + ( value )) 是一样的。因此,下标不仅可以用作数组名,也可以用于指针表达式中。不过这样一来,编译器就很难检查下标的有效性。(斟酌)(意思是如果用指针加下标的方式来表达数组的元素,编译器无法检测到是否越界!)


指针表达式可能比下标表达式效率更高,但下标表达式绝不可能比指针表达式效率更高。但是,以牺牲程序的可维护性为代价获得程序的运行时效率的提高可不是个好主意!

指针和数组并不相等。数组的属性和指针的属性大相径庭!当我们声明一个数组时,它同时也分配了一些内存空间,用于容纳数组元素。但是当我们声明一个指针时,它只分配了用于容纳指针本身的空间。


当数组名作为函数参数传递时,实际上传递给函数的是一个指向数组第一个元素的指针。函数所接收到的参数实际上是原参数的一份拷贝,所以函数可以对其操纵而不会影响实际的参数。但是,对指针参数执行间接访问操作允许函数修改原先的数组元素。数组形参既可以声明为数组,也可以声明为指针。这两种声明形式只有当它们作为函数的形参时才是相等的。


数组也可以用初始值列表进行初始化,初始值列表就是由一对花括号包围的一组值。静态变量(包括数组)在程序载入内存时得到初始值。自动变量(包括数组)每次当执行流进入它们声明所在的代码块时都要使用隐式的赋值语句重新进行初始化。如果初始值列表包含的值的个数少于数组元素的个数,数组最后的几个元素就用缺省值进行初始化。如果一个被初始化的数组的长度在声明中未未出,编译器将使这个数组的长度设置为刚好能容纳初始值列表中所有值的长度。字符数组也可以用一种很像字符串常量的快速方法进行初始化。

例如,字符数组的初始化可以是:

 char message[] = {'H', 'e', 'l', 'l', 'o', 0 };

但是这种方法太笨拙了,可以使用快速初始化方法:

char message[] = "Hello";

上面的两种声明方式,在内存中的存储场景都如下:

'H'

'e'

'l'

'l'

'o'

0


多维数组实际上是一位数组的一种特型,就是它的每个元素本身就是一个数组。多维数组中的元素根据行主序进行存储,也就是最右边的下标先变化。多维数组名的值是一个指向它的第一个元素的指针,也就是一个指向数组的指针。对该指针进行运算将根据它所指向数组的长度对操作数进行调整。多维数组的下标引用也是指针表达式。

当一个多维数组名作为参数传递给一个函数时,它所对应的函数形参的声明中必须显式指明第2维(和接下来的所有维)的长度。由于多维数组实际上是复杂元素的一维数组,一个多维数组的初始化列表就是包含了这些复杂元素的值。这些值的每一个都可能包含嵌套的初始值列表,由数组各维的长度决定。如果多维数组的初始化列表式完整的,它的内层花括号可以省略。在多维数组的初始值列表中,只有第1维的长度会被自动计算出来。

我们还可以创建指针数组。字符串的列表可以以矩阵的形式存储,也可以以指向字符串常量的指针数组存储。在矩阵中,每行必须与最长字符串的长度一样长,但它不需要任何指针。指针数组本身要占用空间,但每个指针所指向的字符串所占用的内存空间就是字符串本身的长度。


编程提示的总结:

一开始就编写良好的代码显然比依赖编译器来修正劣质代码更好;

源代码的可读性几乎总是比程序运行时效率更加重要;

只要有可能,函数的指针形参都应该声明为const;

在有些环境中,使用register关键字提高程序运行时的效率;

在多维数组的初始值列表中使用完整的多层花括号能提高可读性。