1、数组名的值是一个指针常量,它的类型取决于数组元素的类型,数组名的类型就是指向xx类型的常量指针;
2、只有两种场合下,数组名并不用指针常量来表示——就是当数组名作为sizeof操作符或单目操作符&的操作数时,sizeof返回整个数组的长度,而不是指向数组的指针的长度,取一个数组名的地址所产生的是一个指向数组的指针;
3、数组名是一个常量是不能被修改的;
4、除优先级以外,间接引用与下标引用完全一样;间接引用与下标引用可以进行相互转换:
a[3] ===== *(a + (3))
5、下标绝不会比指针更有效率,但是指针有时会比下标更有效率;
6、数组与指针的区别:
(1)声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值是一个常量,指向这段空间的起始位置;
(2)声明一个指针变量时,编译器只为指针本身保留内存空间,它并不为任何整型值分配内存空间,而且,指针变量并未被初始化为指向任何现有的内存空间,如果是一个自动变量,它根本就不会被初始化;
7、所有参数的传递都是通过传值方式进行传递的,如果传递一个指向某个变量的指针,而函数对该指针进行间接访问,那么函数就可以修改那个变量,当然数组名作为参数也是一样的,也是通过传值方式进行传递的,函数得到的是该指针的一份拷贝,它可以被修改,但是调用程序所传递的实参并不受影响(可能修改它所指向的内容);
给个例子好理解:
void strcpy(char *buffer, char const *string)
{
while((*buffer++ = *string++) != '\0')
;
return ;
}
while语句中的*string++表达式取得string指向的那个字符,并且产生一个副作用,就是修改string,使它指向下一个字符,用这种方式修改形参并不会影响调用程序的实参,因为只有传递给函数的那份拷贝进行了修改;
8、对于一个并不打算修改这些字符的函数而言,预先声明为常量是比较好的习惯;
9、如果在程序的执行每次进入该函数(代码块)时,每次都对数组进行重新初始化不是什么有必要,就可以把数组声明为static,这样数组的初始化只需在程序开始前执行一次;
10、
char message[] = "hello";
char *message = "hello";
前者初始化一个字符数组的元素,而后者是一个真正的字符串常量,这个指针变量被初始化指向这个字符串常量的存储位置;
11、在C中,多维数组的元素存储顺序按照最右边的下标率先变化的原则,称为行主序;
12、二维数组名是一个指向数组的指针;
int matrix[3][10];
int *p = matrix;
int **p = matrix;
int (*p)[10] = maxtrix;
以上三种声明只有一个是合法的,首先我们知道matrix是一个指向数组的指针,第一个p是一个指向整型的指针,而第二个是为指向整型指针的指针,只有三个是指向整型数组的指针,故第三个是合法的;
13、作为函数参数的多维数组名的传递方式和一维数组名相同——实际传递的是个指向数组第一个元素的指针,但是两者之间的区别是:多维数组的每个元素本身是另外一个数组,编译器需要知道它的维数,以便为函数形参的下标表达式进行求值;
一维数组的传参:
int vector[10];
func1(vector);
void func1(int *vector);
void func1(int vector[]);
二维数组的传参:
int matrix[3][10];
func2(matrix);
void func2(int (*mat)[10]);
void func2(int mat[][10]);
14、指针数组
int *p[10];
p是指向整型指针的指针;其元素是指向整型的指针;
15、数组形参既可以声明为数组,也可以声明为指针,这两种声明形式只有当它们作为函数的形参时才是相等的;