数组
1.一维数组的创建和初始化
1.1数组的创建
比如:int arr[10];
数组类型 数组名 [常量或者常量表达式]也可以是变量,但只能在支持C99的编译器上编译
1.2数组的初始化
指在创建数组的同时给数组的内容一些合理初始值(初始化)
不完全初始化,剩余的元素默认初始化为0:int arr[10] = {1,2,3};
char ch1[10] = {'a','b','c'};'\0'
char ch2[10]="abc";
1.3一维数组的使用
下标引用操作符(下标从0开始)
数组是使用下标来访问的
数组的大小可以通过计算来得到:int sz = sizeof(arr)/sizeof(arr[0]);
随着数组下标的增长,元素的地址,也在有规律地增长(由低到高),数组在内存中是连续存放的
2.二维数组的创建
2.1二维数组的创建
int arr[3] [4];//3行4列
1 2 3 4
2 3 4 5
3 4 5 6
char arr[3] [5];
double arr [2] [4];
2.2二维数组的初始化
int arr[3] [4]={1,2,3,4,2,3,4,5,3,4};
#include<stdio.h>
int main()
{
//完全初始化
int arr0[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
//不完全初始化
int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4 };
//分组
int arr1[3][4] = { {1,2},{3,4},{5,6} };
//二维数组的行可以省略,但是列一定不能省略!!!
int arr2[][4] = { {1,2,3,4},{2,3} };
}
列数确定下来就可以确定行
2.3二维数组的使用
也是通过下标的方式(下标不管是行还是列都是从0开始的)
可以把二维数组理解为:一维数组的数组
像上面的例子可以看成是含有3个元素的一维数组(每行为一个元素),每个元素是一个一维数组
访问该数组元素
arr[0] [j]
arr[1] [j]
arr[2] [j]
类似于一维数组的访问 arr2[i] (i:1~9)
可以认为arr[0] arr[1] arr[2]都是一维数组名
#include<stdio.h>
int main()
{
int arr[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++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
快速查找数组里面的某一个数
#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
//二维数组的基本访问
int i = 0;
printf("%d\n", arr[2][0]);
/*for (i = 0;i < 3;i++)
{
int j = 0;
for (j = 0;j < 4;j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}*/
return 0;
}
输入数组中的数字,并且按照几行几列输出
#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
//二维数组的基本访问
int i = 0;
//printf("%d\n", arr[2][0]);
for (i = 0;i < 3;i++)
{
int j = 0;
for (j = 0;j < 4;j++)
{
scanf_s("%d", &arr[i][j]);
}
}
for (i = 0;i < 3;i++)
{
int j = 0;
for (j = 0;j < 4;j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
(三维数组也是一样的道理,按照坐标定位元素)
2.4二维数组在内存中的存储
也是连续存储
在内存中的布局方式 int arr[3] [4]<=>int arr2[12]
#include<stdio.h>
int main()
{
int arr[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++)
{
printf("&arr[%d][%d]=%p\n", i, j, &arr[i][j]);
}
}
return 0;
}
每个元素的存储位置都相差4个字节
3.数组越界
数组的下标是有范围的。
数组的下规定是从0开始的,如果数组有n个原元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0.或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
c语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6 };//0-5
int i = 0;
//0-9
for (i = 0;i < 10;i++)
{
printf("%d ", arr[i]);
}
return 0;
}
可以通过计算数组的大小进行检查:
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6 };//0-5
int i = 0;
//0-9
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0;i < sz;i++)
{
printf("%d ", arr[i]);
}
return 0;
}
//二维数组的越界访问
#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int i = 0;
for (i = 0;i < 3;i++)
{
int j = 0;
for (j = 0;j <= 4;j++)
{
printf("%d ", arr[i][j]);
}
}
return 0;
}
4.数组作为函数参数
4.1冒泡排序的正确设计
冒泡排序的核心思想:
两个相邻的元素进行比较
#include<stdio.h>
void bubble_sort(int arr[],int sz)
//形参是指针的形式:void bubble_sort(int* arr,int sz)
{
//趟数
//int sz = sizeof(arr) / sizeof(arr[0]); 地址是应该使用指针来接收,所以arr这里看似是数组,本质是指针变量
int i = 0;
for (i = 0;i<sz-1;i++)
{
//一趟冒泡排序
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;
}
}
}
}
int main()
{
//把数组的数据排成升序
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//冒泡排序的算法,对数组进行排序
bubble_sort(arr,sz);//数组名本质上是:数组首元素的地址
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%d ", arr[i]);
}
return 0;
}
数组传参的时候有2种写法:
1.数组2.指针 如上
4.2数组名是什么
数组名确实能表示首元素的地址
但是有2个例外
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
#include<stdio.h>
int main()
{
int arr[10];
printf("%p\n", arr);
printf("%p\n", &arr[0]);
int n = sizeof(arr);//40
printf("%d\n", n);
return 0;
}
2.取地址&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
#include<stdio.h>
int main()
{
int arr[10];
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%p\n", &arr);
//int n = sizeof(arr);//40
//printf("%d\n", n);
return 0;
}
对比
#include<stdio.h>
int main()
{
int arr[10];
printf("%p\n", 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);
return 0;
}
4.3二维数组的数组名的理解
#include<stdio.h>
int main()
{
int arr[3][4];
int sz = sizeof(arr);
printf("%d\n", sz);
arr;//二维数组的数组名也表示数组首元素的地址,第一行的地址
arr + 1;//第二行的地址
sizeof(arr) / sizeof(arr[0]);//算行数
sizeof(arr[0]) / sizeof(arr[0][0]);//算列数
return 0;
}