目录
一、什么是数组?
二、一维数组的创建和初始化
一维数组的创建
创建方式
初始化
不完全初始化
完全初始化
省略数组长度的初始化
错误示范
字符数组的初始化
三、一维数组的使用
数组长度的计算
数组的下标
四、一维数组在内存中的存储
五、二维数组的创建和初始化
二维数组的创建
二维数组的初始化
不完全初始化
分行初始化
省略行初始化
六、数组的使用
七、二维数组在内存中的存储
八、数组作为函数的参数
数组名是什么
2个例外
案例:冒泡排序
分析
代码实现
一、什么是数组?
数组是一组相同类型元素的集合,这些数据在内存中连续存放
数组不是C语言的专利,Java、C++、C#、JavaScript、PHP 等其他编程语言也有数组
C语言数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。
前面在❤️整理2万字带你走进C语言(详细讲解+代码演示+图解)❤️(强烈建议收藏!!!)这篇文章中已经介绍过数组的基本用法,通过这篇文章我们直接将全面介绍数组,C语言更上一层楼
二、一维数组的创建和初始化
一维数组的创建
创建方式
type_t arr_name[const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
要注意,这里const_n的位置必须是常量表达式,不能用变量
可以先通过以下代码来体验一下
代码1:
int main()
{
int array[10];
}
这段代码里面创建了一个array这样一个数组,数组名为array,数组元素个数10,数组元素类型int
代码2(错误示范):
int main()
{
int count = 10;
int arr2[count];
}
运行结果
这是为什么呢?
就是因为创建数组的时候不能用变量来指定数组的大小
代码3:
char arr3[10];
float arr4[1];
double arr5[20];
这段代码是分别在创建字符数组arr3,float类型数组和double类型数组
初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)
我们刚才的代码1里面创建了一个整型数组,但是数组里面并没有放任何东西,现在我们可以给它初始化一下
不完全初始化
int main()
{
//创建数组并初始化
int arr[10] = { 1,2,3,4,5 }; //不完全初始化 剩余元素默认为0
int arr2[10] = {1,2,3,4,5,6,7,8,9,10}; //完全初始化
int arr3[10] = {0};
int arr4[] = {1,2,3,4};
}
这个arr数组可以放10个元素,但是我们在初始化的时候只放了个1,2,3,4,5这5个元素,剩下的5个元素的位置默认为0,我们可以通过监视器来看一下
可以看到数组arr里面寸的是1,2,3,4,5,0,0,0,0,0
完全初始化
代码1:
int main()
{
//创建数组并初始化
int arr2[10] = {1,2,3,4,5,6,7,8,9,10}; //完全初始化
}
再在监视器里面看arr2数组里面的元素
代码2
int main()
{
//创建数组并初始化
int arr3[10] = {0};
}
省略数组长度的初始化
int main()
{
//创建数组并初始化
int arr4[] = {1,2,3,4};
}
arr4这个数组是不指定数组长度的初始化,日常代码中也经常用,虽然在[ ]里面没有写数组长度,但是你初始化了几个元素,这个数组的长度就是几,也是确定的,在后面初始化了4个元素,那么就相当于[ ]里面是4,写了和没写是一样的
但是要注意,arr4这种写法必须要在创建的时候就初始化,不然就是错误的,编译器推算不出来数组到底多长
错误示范
int main()
{
int arr4[];
}
字符数组的初始化
int main()
{
int ch1[] = "abcde";
int ch2[] = { 'a','b','c','d','e' };
int ch3[3] = {'a','b','33'};
}
这两种初识化的方式都会用到,ch1后面写的是字符串的形式,而ch2里面是直接是单个字符,这两种初始化的方式有什么区别呢?
ch1后面用字符串初始化,后面肯定是有'\0'作为结束标志的
ch2后面都是单个的字符,没有‘’\0
监视器观察:
我们可以通过下面这个题再深刻理解一下:
#include <stdio.h>
int main()
{
char ch1[] = "abcde";
char ch2[] = { 'a','b','c','d','e' };
printf("%d\n", sizeof(ch1));
printf("%d\n", sizeof(ch2));
printf("%d\n", strlen(ch1));
printf("%d\n", strlen(ch2));
return 0;
}
我们可以先想一想,这段代码的执行结果是什么呢?
分析:
ch1和ch2都是字符类型的数组,每个元素占一个字节,ch1里面存放的是字符串,共5个字符还有'\0',所以sizeof(ch1)的值应该是6,strlen(ch1)的值应该是5,ch2数组里面共5个字符,sizeof(ch2)的值应该是5,而ch2后面没有'\0'这个结束标志,所以strlen(ch2)应该是随机值
运行结果:
这里的21就是随机值
三、一维数组的使用
对于数组的使用我们之前介绍了一个操作符: [ ] ,下标引用操作符。它其实就数组访问的操作符
数组长度的计算
这里给大家介绍一种计算数组元素个数(数组长度)的方法
数组长度==数组总大小/数组元素大小
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz);
}
运行结果:
数组的下标
我们平时访问数组都是通过下标来访问的,要注意的是数组的下标并不是从1开始的,而是从0开始的,数组里面每一个元素都对应一个下标
通过以下代码我们来体验一下如何使用数组(对数组的元素进行打印)
#include <stdio.h>
int main()
{
int i = 0;
int arr[] = { 0 };
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 i = 0;
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
//打印数组的元素地址
for (i = 0; i < sz; i++)
{
printf("%p ", &arr[i]);
}
return 0;
}
运行结果:
分析:
整型数组每个元素的大小都是4个字节,我们从运行结果中就能看出每个地址都是相差4,所以可以知道数组的元素在内存中是连续存放的,并且随着数组下标的增长,地址也是由低到高增长的
五、二维数组的创建和初始化
二维数组的创建
//数组创建
int arr1[3][4];
arr1数组是数组名为arr1,数组中的每个元素都是整型如下图示:三行四列的二维数组
二维数组的初始化
不完全初始化
代码如下
int main()
{
int arr[3][4] = { 1,2,3,4,5 }; //不完全初始化
}
这个数组3行4列,可存放12个元素,但只初始化了4个,其余的元素会默认初始化为0,我们可以通过监视器来看一下
分行初始化
如果这里想要将1,2放在第一行,3,4放在第二行,5放在第三行该怎么做呢?如下代码:
int main()
{
int arr[3][4] = { { 1,2 },{ 3,4 },{ 5 } }; //不完全初始化
}
监视器观察:
省略行初始化
int main()
{
int arr[][4] = { { 1,2 },{ 3,4 },{ 5 } }; //不完全初始化
}
这里直接将行数3给省略是完全没有问题的,但要注意,列数是绝对不能省略的
监视器观察:
六、数组的使用
首先来看一下上面的二维数组
如下代码(打印数组中的每个元素):
int main()
{
int arr[][4] = { { 1,2 },{ 3,4 },{ 5 } };
int i = 0; //行
int j = 0; //列
for (i = 0; i < 3; i++) //控制行
{
for (j = 0; j < 4; j++) //控制列
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
运行结果
七、二维数组在内存中的存储
前面我们看到一位数组在内存中是连续存放的,那么二维数组呢?
我们还是将数组的每个元素的地址打印出来看看
#include <stdio.h>
int main()
{
int arr[][4] = { { 1,2 },{ 3,4 },{ 5 } };
int i = 0; //行
int j = 0; //列
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%p\n", &arr[i][j]);
}
}
return 0;
}
运行结果
整型二维数组每个元素的大小也都是4,可以看出二维数组每个元素的地址都是连续的 ,二维数组在内存中也是连续存放的
所以虽然我们的二维数组图是画的3行4列,但这只是为了便于理解,要知道它真正在内存中的存放还是连续的,如下图
我们可以将上面的二维数组理解成是3个一维数组,且这三个一维数组的数组名分别为:arr1[0],arr1[1],arr1[2]
八、数组作为函数的参数
数组名是什么
数组名其实就是数组的首元素地址
我们可以先通过以下代码来看一下:
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", *arr);
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
运行结果:
分析:
可以看到,通过对数组名的解引用,打印出来的就是数组的首元素,而直接将数组名打印出的结果和打印数组首元素地址的结果是一样的,这就可以说明数组名就是数组的首元素地址
2个例外
- sizeof(数组名)----这里的数组名表示的是整个数组
- &数组名----也表示整个数组,取出的是整个数组的地址
案例:冒泡排序
现在有一个数组,我们要对它的元素进行排序
冒跑排序
分析
这里用网上一张动图来清楚的展现冒泡排序的核心思想
这张图清楚的展现了冒泡排序的方法,每一趟冒泡排序都从前到后遍历,相邻元素进行比较,不符合条件的就进行交换,如果数组里有10个元素的话,就需要9躺冒泡排序,每一趟都要比较10-1-趟数对元素
每一趟冒泡排序
一共10个元素就需要9躺
代码实现
#include <stdio.h>
void bubble_sort(int arr[],int sz)
{
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 temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void print_arr(int arr[], int sz) //定义这个函数来打印数组
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
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);
print_arr(arr, sz);
return 0;
}
--------------------------------------------------------------------------------
-------------------------C语言数组部分完结-----------------------------
关于C语言,每个知识点后面都会单独写博客更加详细的介绍
欢迎大家关注!!!
一起学习交流 !!!
让我们将编程进行到底!!!
--------------整理不易,请三连支持------------------