数组
一.初识数组
1.1一维度数组的创建和初始化
-
数组传参的时候,传过去仅仅是首元素的地址,
-
数组的不完全初始化:没有初始化的默认为0.(数组开在main函数之外的时候)
eg:char arr[5]=“ab”; 前三个分别是 a 、b、 \0
1.2. sizeof 和 strlen的区别:
char arr1[] = "abc";
char arr2[] = { 'a','b','c' }; 结果
printf("%d\n", sizeof(arr1)); 4
printf("%d\n", sizeof(arr2)); 3
printf("%d\n", strlen(arr1)); 3
printf("%d\n", strlen(arr2)); 随机数
sizeof 计算的是arr所占空间的大小(会包括\0) n个元素*1=n
strlen 求字符串长度 找到\0就停止 并且\0不算入 求\0之前的字符个数
1.简单地说
sizeof计算的是内存空间大小(包括\0) vs strlen计算第一个\0之前的字符串长度(不算\0)2.sizeof strlen两者没任何关系 一个是关键字 一个是函数
3.strlen只能求字符串长度——并且是库函数,使用时要引头文件
而sizeof是计算变量、数组、类型的大小-单位是字节——本质是操作符/关键字 不需引头文件
1.3一维数组的使用
- 数组的大小可以通过计算来得到
- [] 称为 下标引用操作符
- 这个操作符有什么用呢?
举个栗子:
`int main()`
`{`
`int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };`
`printf("%d", arr[3]);`
`return 0;`
`}`
当我要执行这个语句: printf("%d", arr[3]);
时 打印出来的是什么结果呢?
思考一下 来看答案:
答案是4. 那么为什么这里是4?还有,我上面写着是arr[3],而且中括号里面是依次1-10的排序,为什么不是3呢?
这里有个数组的小细节就是:数组通过下标来访问 并且 元素的下标是从0开始的就像你所看到的1-10的依次排序 谈们的下标依次是0-9
元素:1 2 3 4 5 6 7 8 9 10
下标:0 1 2 3 4 5 6 7 8 9
是这样的对应关系 一定不要搞错
1.4. 一维数组在内存中的储存
- 数组在内存中是连续存放的,相隔的距离是相同的
二.二维数组的创建和初始化
2.1 二维数组的创建
数组创建`
`int arr[3][4];`
`char arr[3][5];`
`double arr[2][4];``
2.2 二维数组的初始化
//数组初始化
`int arr[3][4] = {1,2,3,4};`
`int arr[3][4] = {{1,2},{4,5}};`
`int arr[][4] = {{2,3},{4,5}};`
注意:二维数组的行可以省略,但是列不可以省略。并且不能同时省略
2.3 二维数组的使用
二维数组的使用也是通过下标的方式。
eg:
`\#include <stdio.h>`
`int main()`
`{`
`int arr[3][4] = {0};`
`int i = 0;`
`for(i=0; i<3; i++)`
`{`
`int j = 0;`
`for(j=0; j<4; j++)`
`{`
`arr[i][j] = i*4+j;`
`}`
`}`
`for(i=0; i<3; i++)`
`{`
`int j = 0;`
`for(j=0; j<4; j++)`
`{`
`printf("%d ", arr[i][j]);`
`}`
`}`
`return 0;`
`}`
2.4二维数组在内存中的存储
像一维数组一样,这里我们尝试打印二维数组的每个元素。
`
int arr[3][4];`
`char arr[3][5];`
`double arr[2][4];`
`//数组初始化`
`int arr[3][4] = {1,2,3,4};`
`int arr[3][4] = {{1,2},{4,5}};`
`int arr[][4] = {{2,3},{4,5}};`
注意:二维数组在储存中也是连续的,
数组名==首元素地址(有两个例外)
1).sizeof(数组名)——在这里数组名表示整个数组的大小,,sizeof计算的是整个数组的大小,单位是字节.
2)&数组名,数组名表示整个数组,&数组名,取出的是整个数组的地址
三.数组越界
越界:顾名思义就是超出范围,所以说
-
数组的下标是有范围限制的。
-
数组的下标从0——n-1(假设有n个元素)
所以如果数组的下标<0 或者>n-1 我们把它称为数组越界,即超出了数组合法空间的访问
还要注意:并且c语言的编译器本身不做数组下标的检查,但即使编译器不报错,并不意味程序就没有错误,所以需要自己做好越界的检查。(二维数组也会存在这种越界的情况)
eg:
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i=0; i<=10; i++)
{
printf("%d\n", arr[i]);//当i等于10的时候,越界访问了
}
return 0; }
四.数组的应用&&数组与地址、函数的关系:
4.1数组作为函数参数
当我们写代码的时候,有时候需要将数组作为参数传入函数中,举一个最经典的例子:冒泡排序中就需要将数组中的元素排序(整形数组)
我下意识写了一个代码:
#include <stdio.h>//顾冷————CSDN
void bubble_sort(int arr[])
{
int sz = sizeof(arr)/sizeof(arr[0]);//这样对吗?
int i = 0;
for(i=0; i<sz-1; i++)
{
int j = 0;
for(j=0; j<sz-i-1; j++)
{
if(arr[j] > arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
int main()
{
int arr[] = {3,1,7,5,8,9,0,2,4,6};
bubble_sort(arr);//是否可以正常排序?
for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0; }//CSDN---顾冷
很显然跑出来的结果是错误的,
那么我们要深入了解:
4.2数组名是什么?
随后当我debug的时候发现,bubble_sort内部的sz的大小是1,这里我就很纳闷,为什么数组作为参数的时候不是把整个数组给传递过去呢?如果不是整个数组传过去,那么是传过去了什么呢?
随后上CSDN看大佬们的博客 (上网冲浪)之后,才知道这里传过去的数组名等于首元素的地址 即arr==&arr[0]
其本质就是一个指针 并且大小为4 这么看来 sz==1(整形,指针的大小都是1)这个结果也不足为怪了。
于是 善于总结的我 知道了:
数组名是首元素的地址
补充:
arr 、 arr[0] 都是首元素的地址
但是 &arr 就是整个数组的地址
既然数组名是首元素地址,那么:
int arr[10] = {0};
printf("%d\n", sizeof(arr));
我们都知道,所有东西都不一定是绝对的,当然此处也有2个例外
eg:
- sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数 组。
- &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
综上,可以得出结论:除了1.2补充的情况外,所有的数组名都表示数组首元素的地址。
4.3冒泡函数的正确编程
我在#4.1数组作为函数参数中 写的代码是有问题的(数组传到函数中变成了指针,实际上传过去的arr只是一个摆设 首地址的地址)
即使在函数参数部分写成数组的形式: int arr[] 表示的依然是一个指针: int *arr 。
那么应该怎么修改呢?
首先还是要清楚之前的错误在于 传过去的形参相当于是一个指针了,那么计算sz==_____,的时候就会出现错误,那么我们可不可以先计算出sz,再将sz传到函数中进行计算呢?速度上手试一波
eg://顾冷csdn
```c
```c
```c
void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//每一趟冒泡排序
int flg = 1;//假设要排的数据已经有序
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tep = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tep;
flg = 0;//本次的排序其实不完全有序
}
}
if (flg == 1)
{
break;
}
}
}
int main()
{
int arr[] = {3,1,7,5,8,9,0,2,4,6};
int sz = sizeof(arr)/sizeof(arr[0]);
bubble_sort(arr, sz);//在这里看看,是否可以正常排序?
for(i=0; i<sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
数组的应用(五子棋与扫雷)
时间关系 ,所以这里先鸽~,之后补上详细的应用知识
谢谢大佬们的观看和点赞,如果发现有什么错误的地方请在评论区指出
笔者在此感激不尽~