一、数组定义
1、数组格式: 数据类型 数组名[总个数];
例:
int data[10];
意义:定义一个总个数为10个的数组,它存储的是int(整形)类型的数据。
2、数组下标:
数组的下标为数组中的每一个空间进行编号,从0开始 到 总个数-1。
3、数组中空间的访问:
元素空间名称: 数组名[下标]
元素空间地址: &数组名[下标]
可以将元素空间名称理解为变量名,可以对它进行读写操作。
二、数组空间初始化
数组初始化:定义数组的时候就给空间数据。
例:
1、 int a[3] = {20,40,60};
意义:定义一个名为a的数组,它有三个int类型的空间,给这三个空间赋值为20,40,60。
若要读数据,使用printf。
例如:printf("%d\r\n",a[0]); // 在屏幕上打印a[0]的数值,即为20
2、int a[3] = {20};
这个数组里面的值为 {20,0,0} --- 初始化的时候数据个数小于总个数,其他空间补0
3、int a[3] = {10,4,5,7,8};
这个数组里面的值为 {10,4,5} --- 初始化的时候数据个数超出总个数,后面填的数值舍去
注意:
省略个数的初始化 --- 初始化的时候可以省略个数
int a[] = {1,6,9,100,40}; 问它开了多少空间?
{}中数据的个数 ,即为5个int型的空间
4、拓展数组的长度:
sizeof(a) / sizeof(a[0]) == 20 / 4 == 5
三、二维数组
1、二维数组定义:
多个同种类型的一维数组, 用行和列来进行理解 ,但是真正在内存中是线型。
2、格式:
数据类型 数组名[总行数][总列数];
例如:
存储班级同学的成绩,存储3个班同学的成绩,每个班有5个人。
3行,每一行有5列
float scores[3][5];
3、数据空间:
空间名称:数组名[行下标][列下标]
空间地址:&数组名[行下标][列下标]
例子中的元素一共有:
scores[0][0] scores[0][1] scores[0][2] scores[0][3] scores[0][4]
scores[1][0] scores[1][1] scores[1][2] scores[1][3] scores[1][4]
scores[2][0] scores[2][1] scores[2][2] scores[2][3] scores[2][4]
当我们想输出它的所有元素时,可以使用循环:
int i; // 行号
int j; // 列号
//输入
for(i=0;i<3;i++)
{
// 构造列
for(j=0;j<5;j++)
{
scanf("%f",&scores[i][j]);
}
}
//输出
for(i=0;i<3;i++)
{
// 构造列
for(j=0;j<5;j++)
{
printf("%d ",scores[i][j]);
}
// 2
printf("\n");
}
四、数组分析与地址偏移
1、数组分析:
元素的数据类型 数组名[元素个数];
数组类型:除了 数组名 之外的都属于数组的类型。
元素的类型:除了 数组名[元素个数] 剩下的就是它的元素的类型
例1:
int arr[5];
数组名:arr
数组的类型:int [5]
元素的数据类型:int
元素个数:5
元素的下标:0 1 2 3 4
例2:
int a[2][3];
a的类型是:int [2][3]
a[0]的类型是:int [3]
a[1]的类型是:int [3]
a[0][0]的类型是:int
2、数组中的地址偏移:
>> 数组里面内存空间是连续,--- 看每个空间的地址使用%p
int a[] = {3,5,6};
char b[] = {'A','B','C','D'};
// 输出地址查看内存分配的规律 ---数组空间是连续的
printf("%p %p %p\r\n",&a[0],&a[1],&a[2]);
printf("%p %p %p %p\r\n",&b[0],&b[1],&b[2],&b[3]);
short c[] = {4,7,100,400,3,28,59};
// 假设c数组的起始地址是30H;
// &c[1] = ___32______
// &c[2] = ____34_____
>> 数组名是数组首元素的地址 ---
数组名在大多数场合下代表首元素的地址。
int a[] = {3,5,6};
char b[] = {'A','B','C','D'};
printf("%p %p\r\n",a,&a[0]); // 94 94
printf("%p %p\r\n",b,&b[0]); // 90 90
// sizeof(数组名) --- 这个地方是首元素的地址,它代表数组整个集合。
>> 地址偏移
&x+y的形式,看x的类型,偏移的时候就以x的类型为单位进行偏移。
// 通过数组名的形式对b的元素进行输入赋值
int b[3];
int i;
for(i=0;i<3;i++)
{
scanf("%d",b+i);
}
通过地址获取空间,使用解地址: *(&p) == p
*(a+0) *(a+1) *(a+2)
*(&a[0]) *(&a[1]) *(&a[2])
a[0] a[1] a[2]
*(a+0) = *(a+0) + 1;
一维元素空间的名称和空间的地址2中形式:
数组名 + 下标
元素空间:数组名[下标]
元素地址:&数组名[下标]
数组名+偏移 + 解地址
元素空间:*(数组名+偏移量)
元素地址:数组名+偏移量
二维元素空间的名称和空间的地址2中形式:
数组名 + 行下标 + 列下标
元素空间:数组名[行下标][列下标]
元素地址:&数组名[行下标][列下标]
数组名+行偏移+列偏移 + 解地址
元素空间:*(*(数组名 + 行偏移) + 列偏移) // a[i][j]
元素地址:*(数组名 + 行偏移) + 列偏移 // &a[i][j]