learning_notes_array
- 数组名?你真的了解吗?
- e.g. int a[10]; 数组名a是指向数组第一个元素的地址,类型取决于数组元素的类型。
- 如何理解数组名是一个常量? 不可随意修改。一般来说,在创建数组后,编译后自动为数组分配一个内存地址。当程序运行时,是不可改变内存地址的。
- 数组元素的访问——下标引用 or 指针间接访问?
- C语言中,二者等价。
- 什么意思?举个栗子你就明白啦!a[x] 等价于 *(a + x),(这里x是任意一个常数)。
- so? 下面两个ap[0]、ap[-1]都是合法的!
int array[10];
int *ap = array + 2;
ap[0]; //等价于*(ap+0)即array[2]
ap[-1]; //等价于*(ap-1)即array[1]
- 你以为这就结束了? 不!2[array]这个也是合法的,没想到吧!2[array]等价于*(2 + array)。但是从可读性角度来讲,应该避免这样写。
- 指针引用和下标引用的效率对比
- 指针和下标引用效率相同
a = get_value();
/*下标引用*/
array[a] = 0;
/*指针引用*/
*(array+a) = 0;
- 指针效率高于下标引用
/*下标*/
int array[10], a;
for(a=0; a<10; a++){
array[a] = 0;
}
/*指针*/
int array[10], *ap;
for(ap=a; ap<array+10; ap++){
*ap = 0;
}
- 指针误操作会出现效率低下情况。
- 作为函数参数的数组名
- 形式可以是:int array[] 或者 int *array
- 传址调用体现在:当你对指针间接引用时会修改原本的数组元素
- 传值调用体现在:传递给函数的是指针的拷贝,你可以修改指针而不必担心对于的作为实参的指针。
- 对于多维数组而言,必须告诉编译器数组的维度,因此形参的形式为: int (*mat)[10]或者 int mat[][10]
- 数组初始化
- static静态初始化:只初始化一次
- auto自动初始化:每次进入作用域时都会初始化一次
- 不完整初始化:数组未赋值的元素自动初始化为0
- 字符串和字符数组
-
char message[] = {'H','e','l','l','o',0};
-
char message[] = "Hello";
-
上述两种写法是等价的,都是声明的一个字符数组
-
char message[] = "Hello";
-
char *message = "Hello";
-
上述两种写法意义不同,第一种是字符数组,而第二种则是字符常量。
- 多维数组的存储顺序
int matrix[6][10];
int *mp;
mp = &matrix[3][8];
- 对于*mp 表示 matrix[3][8];
- 对于*++mp 表示 matrix[3][9];
- 对于*(mp+2) 表示 matrix[4][0];
- 多维数组名
- matrix实际就是第一个元素的地址,也是指向第一个数组单元的地址,即matrix[0][0]的地址
- matrix+1表示指向下一个数组单元的地址,即matrix[1][0]的地址,*(matrix+1)表示第二个数组单元的第一个数,即matrix[1][0]
- *(matrix+1)+5表示matrix[1][5]的地址, 而
*(*(matrix+1)+5)
表示matrix[1][5] *(*(matrix+1)+5)
等价于*(matrix[1]+5)
- 多维数组的指针操作
int matrix[3][10]; *mp = matrix;
是非法的- 原因是:matrix是一个指向整型数组的指针,而mp是一个指向整型变量的指针。修改:
int (*p)[10] = matrix;
这样才合法, p指向matrix的第一个数组单元(指向matrix的第一行) int *p1 = &matrix[1][0]; int *p2 = matrix[1];
两者相等价