回过头来复习基础,打铁需要自身硬
一概述:
数组在C语言中有着特殊的地位,它有很多特性,例如它的存储是连续的,数组的名称就是数组的地址等。
二. 一维数组:
1.注意:
1.数组长度必须是固定的,必须为常量或常量表达式(2+1,2*3)或者不写,不能使用变量进行初始化。
int len = 2;
int a[len] = { 1, 2};//错误,不能使变量
2.如果声明的同时进行赋值则长度可以忽略,编译器会自动计算素组长度。
int b[] = { 1, 2, 3 };
//如果初始化的同时赋值则数组长度可以省略,当前长度个数为3
3.数组不能先声明再一次性赋值.(当然可以对每一个元素一一赋值)
//错误:
int len[2]; //len == &len[0]第一个元素的地址就是整个数组的地址,
len = {1,2,3}; //len是数组名,代表数组的地址,也是个常量,给常量赋值肯定是错的。
len[2] = {1, 2, 3}; // 错误,代表着数组第3个元素,这里已经数组下标越界了,就算没有越界,应该赋值int类型不应该是{}.
//正确:
int c[2];
c[0] = 1;
c[1] = 2;
c[2] = 3;//超过数组长度,但是编译器并不会检查,运行报错,数组遍历从下标0开始遍历,元素不能超过长度,否则数组越界.{leng-1};
4.在计算机中,遍历一般是从0开始遍历, 数组长度就是跟现实生活一样从1开始.
int b['a'] = {1,2,3};//'a'=97,所以可以作为数组长度,但是后面的元素没有初始化,其值默认为0
for (int i = 0; i < 97; ++i){
printf("b[%d]=%d\n",i,b[i]);
}
5.只能存放一种类型的数据,如全部是int型或者全部是char型,数组里的数据成为元素.
2.1.数组存储
刚刚上面说了,知道 数组类型 和 数组名(等于第一个元素的地址) 就可以知道其他元素的地址.即第一个元素的地址就是整个数组的地址
#include <stdio.h>
int main(){
int const l = 3;
int a[l] = { 1, 2,3 };
for (int i = 0; i < l; ++i){
//由于当前在32位编译器下,int型长度为4个字节,可以判断出三个地址两两相差都是4
printf("a[%d]=%d,address=%x\n", i, a[i], &a[i]);
}
/*当前输出结果:
a[0] = 1, address = c9f95c
a[1] = 2, address = c9f960
a[2] = 3, address = c9f964*/
}
额外:数组名代表着整个数组的地址,如果一维数组的名字作为函数实参,传递的是整个数组,即形参数组和实参数组完全等同,是存放在同一存储空间的同一个数组。这样形参数组修改时,实参数组也同时被修改了
#include <stdio.h>
//形参
void changeValue(int a[]){
a[0] = 10;
}
int main(){
int a[2] = {1,2};
changeValue(a); //实参
for (int i = 0; i < 2; ++i){
printf("a[%d]=%d\n",i,a[i]);
} /*打印结果
a[0]=10
a[1]=2
*/
}
如果把一位数组的元素(a[0])作为函数的实参,只是把元素的值传给形参,形参不会改变实参三.多维数组:
二位数组是一个特殊的一维数组,它的元素是一位数组.
例如int a[2][3]可以看作由一维数组a[0]和一维数组a[1]组成,这两个一维数组都包含了长度为3的int类型3个元素
int a[2][3] = { {2, 2, 3}, {3, 4, 5} };
* 二维数组的存放顺序是按行存放的,先存放第一行的元素,再存放第2行的元素。例如int a[2][3]的存放顺序是:a[0][0] → a[0][1] → a[0][2] → a[1][0] → a[1][1] → a[1][2]
#include <stdio.h>
int main(){
int a[2][3];//2行3列,二维数组可以看成是一个特殊的一维数组,只是它的每一个元素又是一个一维数组
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
for (int i = 0; i < 2; ++i){
for (int j = 0; j < 3; ++j){
printf("a[%d][%d]=%d,address=%x\n", i, j, a[i][j], &a[i][j]);
}
}
/*打印结果
a[0][0]=1,address=f8fb24
a[0][1]=2,address=f8fb28
a[0][2]=3,address=f8fb2c
a[1][0]=4,address=f8fb30
a[1][1]=5,address=f8fb34
a[1][2]=6,address=f8fb38
*/
//初始化并直接赋值
int b[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
//由于数组的赋值顺序是先从第一行第一列,再第一行第二列...然后第二行第一列...,所以我们也可以写成如下形式
int c[2][3] = { 1, 2, 3, 4, 5, 6 };
//也可以只初始化部分数据,其余元素默认为0
int d[2][3] = { 1, 2, 3, 4 };
for (int i = 0; i < 2; ++i){
for (int j = 0; j < 3; ++j){
printf("d[%d][%d]=%d\n", i, j, d[i][j]);
}
}
/*打印结果
d[0][0]=1
d[0][1]=2
d[0][2]=3
d[1][0]=4
d[1][1]=0
d[1][2]=0
*/
//当然下面赋值也可以
int e[2][3] = { {}, { 4, 5, 6 } };
//可以省略行号,但是绝对不可以省略列号,因为按照上面说的赋值顺序,它无法判断有多少行
int f[][3] = { {1,2,3},{4,5,6} };
}
存储内存:
a[0]、a[1],也是数组,是一维数组, 而且a[0]、a[1]就是数组名,因此a[0]、a[1]就代表着这个一维数组的地址.
1> 数组a的地址是f8fb24,数组a[0]的地址也是f8fb24,即a = a[0];
2> 元素a[0][0]的地址是f8fb24,所以 数组a[0]的地址 和 元素a[0][0]的地址 相同,即a[0] = &a[0][0];
3> 最终可以得出结论:a = a[0] = &a[0][0],以此类推,可以得出a[1] = &a[1][0]