一.什么是数组:
我们都知道,想要将数据放入内存,需要先创建合适的数据类型变量,根据变量数据类型分配内存空间,想要存入4个 int 类型数据则需要创建四个 int 类型变量。想想也能明白,根据数据数量不停的创建变量,这样的效率非常低,也会让代码又臭又长。而数组完美解决了这个问题。
数组(Array),顾名思义就是两个或者多个数据的集合,,它所包含的每一个数据叫做 数组元素 (Element),所包含的数据的个数称为 数组长度 (Length),数组中的每个元素都有一个序号,这个序号从0开始,而不是从我们熟悉的1开始,称为 下标 (Index),所包含数组的里面元素的类型叫做 数组类型 (Type)。
二.数组的创建:
数组可以有多种创建方式,每种方式对应不同的应用场景。
1).声明数组时指定数组的长度:
首先是数组最基础的创建方式:
示例:
#include<stdio.h>
int main()
{
int a[10] = { 0 };
return 0;
}
显而易见,这里创建了一个可以储存十个 int 类型数据的数组 a ,并初始化为0;
当数组的数据类型是 char 类型时,需要注意不要漏掉 '\n' ,否则造成内存访问越界,产生未知的结果;
示例2:
#include<stdio.h>
int main()
{
char a[3] = { 'a','b','c' };
printf("%s", a);
return 0;
}
运行结果如下图所示:
当我们在 'c' 后方加入终止符时:
示例3:
#include<stdio.h>
int main()
{
char a[4] = { 'a','b','c','\0'};
printf("%s", a);
return 0;
}
运行结果如下图所示:
显而易见的,加入 '\0' 后打印出来的就是正确的数组内容了。
每个数组后面都要加入 '\0' ,并且每一次初始化都要写很多引号和逗号,这非常麻烦,由此,我们可以这样初始化:
示例4:
#include<stdio.h>
int main()
{
char a[4] = "abc";
printf("%s", a);
return 0;
}
使用双引号的数组进行初始化,在数组末尾默认存在终止符。
注:当[]内长度为变量时,在部分编译器下报错,部分编译器下正常运行。(变长数组)
2).使用初始值初始化长度:
示例:
#include<stdio.h>
int main()
{
char a[] = "abcd";
printf("%s",a);
return 0;
}
运行结果如下图所示:
当数组的值在开发时即已经确定时,可以使用此语法,比如在进行身份证最后一位的合法性验证时用到的校验码,还有小写数字转中文大写数字时的大写数字都可以使用这个语法。
3).使用动态方式为数组分配内存:
关键函数 malloc realloc
示例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
char* a = (char*)malloc(sizeof(char) * 10);
strcpy(a, "abc");
printf("%s", a);
return 0;
}
运行结果如下图所示
此方式可用于函数数组的返回,由于在函数内定义的数组属于函数的局部变量,在其它函数中无法访问此变量。使用malloc动态分配空间可解决此问题
注:动态内存分配需要一个内存管理程序,记录内存的分配大小、释放节点、空余节点,甚至添加一堆调试信息,这些操作需要额外占用内存,因此,实际使用的物理内存会大于申请的内存空间。 其次,频繁的不同长度的动态内存分配与释放可能造成内存碎片。
三.二维及多维数组:
二维数组的声明格式:
二维数组逻辑表达:
示例:
#include<stdio.h>
int main()
{
int a[2][3] = { 1,2,3,4,5,6 };
return 0;
}
这里,我们声明了一个两行三列、数据类型为 int 类型的数组。
二维数组的本质也是数组,只不过其中的数组元素也为数组,多维数组亦是如此。
注:二维数组列上的数字可以省略,但是表示行的数字不能省略。
四.数组的储存方式:
逻辑结构:线性。
物理结构:线性。
物理结果证明:
#include<stdio.h>
int main()
{
char a[20];
int b = 0;
while (b < 20)
{
printf("%p\n", &a[b]);
b++;
}
return 0;
}
运行结果如下图所示:
我们可以看出数组元素之间相距均为一,可知数组元素在内存中按顺序线性排列。