数组的概念:
- 数组(Array),是多个
相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。 
数组的格式:
如:int a[5];
数组名—->a
下标(或索引、index)—->a[0]….a[4]
元素—->a[0]等于的值
数组的长度—->5
数组的特点:
数组中的元素在内存中是依次紧密排列的,有序的。
创建数组对象会在内存中开辟一整块
连续的空间。占据的空间的大小,取决于数组的长度和数组中元素的类型。我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
数组,一旦初始化完成,其长度就是确定的。数组的
长度一旦确定,就不能修改。数组名引用的是这块连续空间的首地址。
一维数组:
数组名,记录该数组的首地址 ,即 a[0]的地址。
C 语言规定,数组变量一旦声明,数组名指向的地址就不可更改。
数组通过变量名后加方括号表示,方括号里面是数组可以容纳的成员数量(即长度)。
**注意:**声明数组时,必须给出数组的大小。
解释:

数组元素的调用:
格式:
数组名[下标]数组的
下标从0开始,用“int arr[10];”定义数组,则最大下标值为9,不存在数组元素arr[10]。1
2arr[0] = 13; //对该位置数组元素进行赋值
int score = arr[0]; //调用此位置的元素值
关于长度:
数组的字节长度:
- sizeof 运算符会返回整个数组的字节长度。
 
1
2int arr[10];
printf("数组的字节长度为:%zd\n",sizeof(arr)); //40数组的长度:
- 在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
 - 由于数组成员都是同一个类型,每个成员的字节长度都是一样的,所以数组整体的字节长度除以某个数组元素的字节长度,就可以得到数组的成员数量。
 - 注意:数组一旦声明/定义了,其长度就固定了,不能动态变化。
 
定义方式:
数组可以在声明时,使用大括号,同时对每一个成员赋值。
1
int arr[5] = {22, 37, 90, 48, 95};
C 语言允许省略方括号里面的数组成员数量,这时根据大括号里面的值的数量,自动确定数组的长度。
1
2
3int arr[3] = {10,20,30};
// 等同于
int arr[] = {10,20,30}; //数组arr的长度,将根据大括号里面的值的数量,确定为 3对数组部分元素赋初值:如果大括号里面的值,少于数组的成员数量,那么未赋值的成员自动初始化为 0 。
1
2
3int arr[5] = {10, 20, 30};
// 等同于
int arr[5] = {10,20,30, 0, 0};将整个数组的每一个成员都设置为零,最简单的方式如下
1
int a[100] = {0};
数组初始化时,可以指定为哪些位置的成员赋值。
1
2
3int arr[15] = {[2] = 10, [5] = 20, [14] = 30}; //非角标2、5、14的位置自动赋值为0
//等同于
int arr[15] = {[5] = 20, [14] = 30, [2] = 10}; //指定位置的赋值可以不按角标从小到大的顺序
memcpy()函数:
memcpy() 函数定义在头文件 string.h 中,直接把数组所在的那一段内存,再复制一份。3个参数依次为:
目标数组、源数组以及要复制的字节数。1
2
3
4int a[3] = {10, 20, 30};
int b[3];
// 使用 memcpy 函数复制数组 a 到数组 b
memcpy(b, a, 3 * sizeof(int));
char型数组与字符串:
字符型数组,顾名思义,数组元素的数据类型为字符型的数组。
一方面,可以看做普通的数组,初始化、常用操作如前所述,另一方面,字符型数组可以用于存储字符串。
1
2char arr[] = {'a','b','c','d'};//数组长度为5,最后不加\0
char arr[]="helloworld";//数组长度为11,会在最后自动加1个\0C语言没有专门用于存储字符串的变量类型,字符串都被存储在char类型的数组中。在字符串结尾,C 语言会自动添加一个
'\0'的转义字符作为字符串结束的标志,所以字符数组也必须以 ‘\0’字符结束。如果一个字符数组声明如下,由于必须留一个位置给
\0,所以最多只能容纳9个字符的字符串。1
char str1[10];
字符串的长度:
1
char nation[10]={"China"};
数组nation的前5个元素为: ′c′,′h′,′i′,′n′,′a′,第6个元素为′\0′,后4个元素也自动设定为空字符。
**注意:**在计算字符串长度的时候,’\0’ 是结束标志,不算作字符串内容。
1
2
3
4
5
6
7
int main() {
char nation[10] = "China";
printf("%d\n", strlen(nation));//5
}
解释说明:
1
2
3char s1[50] = "hello"; //声明1
char s2[] = "hello"; //声明2
char s3[5] = "hello"; //声明3- 声明1:赋给的元素的个数小于该数组的长度,则会自动在后面加 ‘\0’, 表示字符串结束。所以,字符数组 s1 的**
长度是 50** ,但是字符串“hello”的**实际长度只有5**(不包含结尾符号 ‘\0’ ),所以后面空出来的45个位置,都会被初始化为 ‘\0’。 - 声明2:字符数组 s2 的**
长度是 6(包含结尾符号 ‘\0’ ),但是字符串“hello”的实际长度只有5**。 - 声明3:赋给的元素的个数等于该数组的长度,则不会自动添加 ‘\0’。但字符串要求以’\0’结束,所以这种写法是**
错误的**,要避免。 
- 声明1:赋给的元素的个数小于该数组的长度,则会自动在后面加 ‘\0’, 表示字符串结束。所以,字符数组 s1 的**
 比较**”x”和‘x’**的不同:
- 书写形式不同:字符串常量用双引号,字符常量用单引号。
 - 存储空间不同:在内存中,字符常量只占用一个字节的存储空间,而字符串存储时自动加一个结束标记’\0’,所以’x’占用1个字节,而”x”占用2个字节。
 - 二者的操作也不相同。例如,可对字符常量进行加减运算,字符串常量则不能。
 
二维数组:
定义的时候,可以不给出行数,但必须要给出列数(不建议不给出行数)
定义方式:
- int a[3][4]; 表示这个数组是3行4列的
 - 可以理解成一栋楼有3层,每层有4个房间
 
解释说明:
在
内存中,各元素是连续存放的,不是二维的,是线性的。C语言中,二维数组中元素排列的顺序是
按行存放的。即:先顺序存放第一行的元素,再存放第二行的元素。(最右边的下标变化最快,第一维的下标变化最慢)。
冒泡和选择排序:
- 冒泡排序:比较相邻的元素并交换它们的位置,从而将较大的元素逐渐“冒泡”到数组的末尾
- 外层循环是控制比较总轮数:比如10个数,只需确定9个数的位置就行,另1个也就确定了,所以外层循环为n-1
 - 内层循环是控制比较相邻元素:因为是俩俩比较,所以假如有10个数,只需比较9次,但是每当外层循环确定一次,也就是确定了1个数的位置,也就不需要再比较了,所以为n-1-外层循环次数
 - 公式总结:
- 外层为:n-1
 - 内层为:n-1-外层循环次数
 
 
 - 选择排序:每次从未排序的部分中选择最小(或最大)的元素,将其放到已排序部分的末尾。
- 外层循环是控制比较总轮数:比如10个数,拿第1个和另外9个依次比较,所以外层循环为n-1
 - 内层循环是控制每次比较次数:比如10个数,外层每循环一次,在开头确定一个位置,所以内层每次循环是在外层循环加1的基础上执行的
 - 公式总结:
- 外层:n-1
 - 内层:int j=外层轮数+1,j<n(总数据)
 
 
 
步长计算:
1  | int arr[2][3]={  | 
| 表达式 | 类型 | 步长 | 典型操作实例 | 
|---|---|---|---|
| &arr | int (*)[2][3] | 24字节(23sizeof(int)) | 极少用于指针运算,因为会越界 | 
| arr | int (*)[3] | 12字节(3*sizeof(int)) | arr+1 跳一行 | 
| arr[0] | int * | 4字节(sizeof(int)) | arr[0]+1 跳下一个元素 | 
| &arr[0][0] | int * | 4字节(sizeof(int)) | &arr[0][0]+1 <=> &arr[0][1] | 
| arr[0][0] | int | 无 | 直接取值 |