4.数组
数组是一组相同类型元素的集合。
4.1 一维数组的创建和初始化
4.1.1 创建
// 格式:
type_t arr_name [const_n]
// type_t 数组元素类型
// arr_name 数组名称
// const_n 常量表达式,指定数组大小
// 在VS2019、VS2022中不支持变长数组
// 在gcc编译器中支持
// 创建
int arr[10];
4.1.2 初始化
int main()
{
int arr1[3] = {0, 1, 2}; // 完全初始化
int arr2[3] = {1, 2}; // 不完全初始化
int arr3[] = { 2, 4, 6, 8 }; // 自动确定数组长度
int arr4[5] = { 2, 4, 6, 8 }; // 与上一条语句等价
int arr5[10] = { 0 } // 不完全初始化,不是把10个元素全初始化为0
int arr6[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
char ch1[5] = "ccc"; // 'c' 'c' 'c' '\0' 0
char ch2[] = "ccc"; // 'c' 'c' 'c' '\0'
char ch3[] = { 'c', 'c', 'c' }; // 'c' 'c' 'c'
printf("%s\n", ch1);
printf("%s\n", ch2);
printf("%s\n", ch3);
return 0;
}
4.2 一维数组的使用
4.2.1 获取
[] // 下标引用操作符
int arr[5] = { 1, 2, 3, 4, 5 };
arr[3]; // 获取数组arr中下标为3的元素的值
4.2.2 赋值
arr[3] = 444;
4.2.3 数组中元素的个数
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
int size = sizeof(arr) / sizeof(arr[0]); // 获取数组中元素的个数
// sizeof(arr)获取的是整个数组的大小,单位是字节
printf("%d\n", size);
}
4.3 一维数组在内存中的存储
4.3.1 %x和%p的区别
int main()
{
printf("%x\n", 0x5f);
printf("%p\n", 0x5f);
return 0;
}
// 指针是有长度的
4.3.2 存储方式
int main()
{
int arr[5] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 5; i++)
{
printf("&arr[%d] => %p\n", i, &arr[i]);
}
}
// 现象:下标每增加1,地址变化4字节,刚好是int类型的大小
// 结论:
// 一维数组在内存中是连续存放的
// 随着数组下标的增长,地址是由低到高变化
4.3.3 应用
// 对于int指针,p++,每次增加int类型的字节数(4byte)
// 对于char指针,p++,每次增加char类型的字节数(1byte)
4.4 二维数组的创建和初始化
int main()
{
// 创建
int arr[3][4]; // 三行四列
char ch[3][4];
double dou[3][4];
// 初始化
int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; // 完全初始化
int arr2[3][4] = { {1, 2},{3, 4},{5, 6} }; // 每行初始化
int arr3[][4] = { {1, 2},{3, 4},{5, 6} }; // 省略行(但不能省略列)
int ch[3][4] = {'h','e','l','l','o'}; // 不完全初始化
return 0;
}
4.5 二维数组的使用
int main()
{
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
for (int i = 0; i < 3; i++)
{
for ( int j=0; j<4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
4.6 二维数组在内存中的存储
int main()
{
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
printf("arr[%d][%d]=%p\n", i, j, &arr[i][j]);
}
}
return 0;
}
// 现象:每个元素相差4byte,恰好是int类型的大小
// 二维数组在内存中连续存放
4.7 数组作为函数参数
4.7.1 数组名
数组名是数组首元素的地址。
- 例外
- sizeof(arr)获取的是整个数组的长度,单位:byte。
- &arr获取的是整个数组的地址。
int main()
{
int arr[5] = { 0 };
printf("arr => %p\n", arr);
printf("arr => %p\n", arr+1);
printf("&arr => %p\n", &arr);
printf("&arr => %p\n", &arr+1);
printf("&arr[0] => %p\n", &arr[0]);
printf("&arr[0] => %p\n", &arr[0]+1);
return 0;
}
4.7.2 冒泡排序
// 两两相邻元素进行比较
void bubble_sort(int arr[], int count) // 形参arr本质是指针
{
int i = 0; // 确定趟数
for ( i = 0; i < count; i++)
{
int j = 0; // 每趟比较元素的次数
for ( j = 0; j < count-1-i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 1, 6, 3, 9, 4 };
int count = sizeof(arr) / sizeof(arr[0]); // 确定数组元素个数
bubble_sort(arr, count); // 数组在传参时,传递的时arr首元素的地址
for (int i = 0; i < count; i++) // 打印排序结果
{
printf("arr[%d]=%d\n", i, arr[i]);
}
return 0;
}
4.8 练习
4.8.1 逆序数组中元素个数
void reverse(int arr[], int size)
{
int left = 0;
int right = size-1;
while (left<right)
{
int tmp = 0;
tmp = arr[right];
arr[right] = arr[left];
arr[left] = tmp;
left++;
right--;
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int size = sizeof(arr) / sizeof(arr[0]);
reverse(arr, size);
return 0;
}
4.8.2 交换数组
将数组A中的内容和数组B中的内容进行交换(数组一样大)
int main()
{
int arr1[3] = { 1, 2, 3 };
int arr2[3] = { 4, 5, 6 };
// 错误操作:
//int arr3[3] = { 0 };
//arr3 = arr2;
//arr2 = arr1;
//arr1 = arr2;
// 元素可以相互赋值,但数组名不可以相互赋值,因为数组名是数组首元素的地址
//
// 正确操作:
int size = sizeof(arr1) / sizeof(arr1[0]);
for (int i = 0; i < size; i++)
{
int tmp = 0;
tmp = arr1[i];
arr1[i] = arr2[i];
arr2[i] = tmp;
}
return 0;
}
4.9 实例
4.9.1 三子棋
4.9.2 扫雷