#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//---------------------------------------------------------------------------------------2. 二维数组的创建和初始化
//-------------------------------------------------------------------------------------------------2.1 二维数组的创建
// 1 2 3 4
// 2 3 4 5
// 3 4 5 6
int main()
{
int arr1[3][4]; // (3行4列)
char arr2[5][10]; // (5行10列)
double arr3[6][6]; // (6行6列)
return 0;
}
//-------------------------------------------------------------------------------------------------2.2 二维数组的初始化
int main()
{
int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
// 1 2 3 4
// 2 3 4 5
// 3 4 5 6
int arr2[3][4] = { 1,2,3,4,2,3,4,5,3,4 }; // 如果元素不够,用0补齐(不完全初始化)
// 1 2 3 4
// 2 3 4 5
// 3 4 0 0
int arr3[3][4] = { {1},{2,3},{3,4,5} }; // 可以再分组(不完全初始化)
// 1 0 0 0
// 2 3 0 0
// 3 4 5 0
//二维数组 可以省略 行 数,不能省略 列 数
int arr3[][4] = { {1,2,3,4},{2,3} }; //行数输入了几行,就是几行
// 1 2 3 4
// 2 3 0 0
return 0;
}
//-------------------------------------------------------------------------------------------------2.3 二维数组的使用
// 二维数组的使用也是通过下标的方式
//不管是 行 还是 列 都是从0开始访问
int main()
{
//int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
//----------------------------------------------------自己 输入一个 二维数组
int arr1[3][4] = { 0 };
int i = 0;
for (i = 0; i <3; i++)
{
int j = 0;
for (j = 0; j <4; j++)
{
scanf("%d", &arr1[i][j]);
}
}
//---------------------------------------------------- 打印 整个 二维数组
for (i = 0; i <= 2; i++)
{
int j = 0;
for (j = 0; j <= 3; j++)
{
printf("%d ", arr1[i][j]);
}
printf("\n");
}
//--------------------------------------------------------打印数组中的某个元素
printf("%d\n", arr1[2][2]); // 打印 3行 3列 位置的元素
printf("%d\n", arr1[2][0]); // 打印 3行 1列 位置的元素
return 0;
}
//可以把二维数组理解为由一维数组组成的数组
访问第一行元素 arr[0][j]
访问第二行元素 arr[1][j]
访问第三行元素 arr[3][j]
//-----------------------------------------------------------------------------------------2.4 二维数组在内存中的存储
// 打印出 二维数组中的地址
int main()
{
int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
int i = 0;
for (i = 0; i <= 2; i++)
{
int j = 0;
for (j = 0; j <= 3; j++)
{
printf("&arr1[%d][%d]=%p\n", i,j,&arr1[i][j]);
}
}
return 0;
}
//二维数组在内存中也是 连续存放的,各相差4个字节(一个字符四个字节)
&arr1[0][0]=00000027016FF598
&arr1[0][1]=00000027016FF59C
&arr1[0][2]=00000027016FF5A0
&arr1[0][3]=00000027016FF5A4
&arr1[1][0]=00000027016FF5A8
&arr1[1][1]=00000027016FF5AC
&arr1[1][2]=00000027016FF5B0
&arr1[1][3]=00000027016FF5B4
&arr1[2][0]=00000027016FF5B8
&arr1[2][1]=00000027016FF5BC
&arr1[2][2]=00000027016FF5C0
&arr1[2][3]=00000027016FF5C4
//二维数组 可以省略行数,不能省略 列 数
// int arr[][4]={1,2,3,4,5,6};
//---------------------------------------------------------------------------------------------------------------3.数组越界
数组的下标是有范围限制的。
数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
所以程序员写代码时,最好自己做越界的检查。
//------------------------------------------------一维
int main()
{
int arr1[] = { 1,2,3,4,5,6 };
int sz = sizeof(arr1) / sizeof(arr1[0]); //用公式计算得到数组大小
int i = 0;
for (i = 0; i < sz; i++) //写 sz 避免出现数组越界访问
// for (i = 0; i < 9; i++) // 数组越界
{
printf("%d ", arr1[i]);
}
return 0;
}
//-----------------------------------------------二维
int main()
{
int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
int i = 0;
for (i = 0; i <3; i++)
{
int j = 0;
for (j = 0; j <4; j++)
// for (j = 0; j <= 4; j++) //数组越界
{
printf("%d ", arr1[i][j]);
}
printf("\n");
}
return 0;
}
//--------------------------------------------------------------------------------------------------4.数组作为函数参数
//写代码时,常常会将数组作为参数传给函数。比如实现一个冒泡程序
//冒泡排序的核心思想,两个相邻的元素进行比较
//一趟冒泡排序让一个数据来到他最终应该出现的位置
//----------------------------------------------------------------------------------------4.1 冒泡排序函数的错误设计
//数组传参,形参有两种写法: 1.数组 2.指针
//-------------------------------------失败原因------------------------------------
数组传参传的是数组内元素的首地址
地址应该使用指针来接收
所以 这里的 形参 int arr[],表面上是数组,本质上是个指针变量
因此 sizeof(arr) 计算出来的就不是数组大小了,是指针大小4(x86环境)
sizeof(arr[0]) 也是4
所以 sz 求出来为 1,导致冒泡失败
修改方法,把 sz 放到函数外部求,传到函数内部
void bubble_sort(int arr[], int sz) // 1. 形参是数组形式:便于理解。 []数值可写可不写
//void bubble_sort(int* arr, int sz) // 2. 形参是指针形式
{
//确定需要多少趟冒泡排序(也就是数组元素个数-1)
//int sz = sizeof(arr) / sizeof(arr[0]); //失败原因,解决方法就是sz 在外部求,传到内部 -----------0 1 2 3 4 5 6 7 8 9 -----冒泡成功
int i = 0;
for (i = 0; i < sz - 1; i++) //sz-1趟冒泡排序
{
//一趟冒泡排序
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
//交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
//void bubble_sort(int* arr) // 2. 形参是指针形式:
//{
//
//}
int main()
{
//把数组内容排成升序
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//冒泡排序算法,对数组进行排序
//bubble_sort(arr); // 数组名本质是数组首元素的地址---------------------------失败原因
bubble_sort(arr,sz); //数组传参,给数组名就行,把数组元素个数也传过去
// 打印出来
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]); // 8 9 7 6 5 4 3 2 1 0-------------------------冒泡失败
}
return 0;
}
//------------------------------------------------------------------------------------------------4.2 数组名是什么?
//数组名确实能表示首元素的地址
//但是有两个例外
// 1. sizeof(数组名), 这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
// 2. &数组名, 这里的数组名也表示整个数组,取出的是 整个数组的地址
//除了这两种情况之外,以后见到的所有的 数组名arr, 代表的都是首元素地址
int main()
{
int arr[10];
printf("%p\n", arr); // 打印数组名 arr 首元素的地址
printf("%p\n", arr+1);
printf("---------------------------------------\n");
printf("%p\n", &arr[0]); //打印首元素地址
printf("%p\n", &arr[0]+1);
printf("---------------------------------------\n");
printf("%p\n", &arr); // 打印数组的地址
printf("%p\n", &arr+1);
// 000000148B8FFB78 //跳了4个字节,1个元素
// 000000148B8FFB7C
// -------------------------------------- -
// 000000148B8FFB78 //跳了4个字节,1个元素
// 000000148B8FFB7C
// -------------------------------------- -
// 000000148B8FFB78 //跳了40个字节,整个数组的10个字节
// 000000148B8FFBA0
int n = sizeof(arr);
printf("%d\n", n); // 算出 40,数组的大小,40个字节
return 0;
}
//------------------------------------二维数组数组名的理解
int main()
{
int arr[3][4];
int sz = sizeof(arr); //计算整个元素的大小 12个元素,每个元素4个字节
printf("%d\n", sz); // 输出 48 (3*4*4)
arr; // 二维数组的数组名 表示的是 第一行(首行) 的地址,不是0*0元素的地址
printf("%p\n", arr);
printf("%p\n", arr + 1);
// 000000A2C0AFFCC8 跳过16个字节,4个元素,也就是跳过一行
// 000000A2C0AFFCD8
printf("%d\n", sizeof(arr) / sizeof(arr[0])); //计算数组的行数(数组所有字节 / 数组每行的字节数)
printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0])); //计算数组的行数(数组首行字节数 / 数组一个字节数)
return 0;
}