玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!


文章目录

  • 前言
  • 1、数组是什么
  • 2、一维数组
    • 2.1一维数组的创建
    • 2.2一维数组的初始化
    • 2.3一维数组的使用
    • 2.4一维数组在内存中的存储
  • 3、二维数组
    • 3.1二维数组的创建
    • 3.2二维数组的初始化
    • 3.3 二维数组的使用
    • 3.4 二维数组在内存中的存储
  • 4、数组越界
  • 5、数组名的探讨
  • 最后

前言 数组的作用在程序编程中的重要性不言而喻。它是指相同类型元素的一组集合。
比如油烟机的风扇转速会和工作的模式之间有一定的关系,那么我们就可以把它的工作模式和一维数组的下标对应起来,我们将具体的转速放在数组中,这样的话就非常方便我们在日后查询。
在程序中合理地使用数组,会使程序的结构比较整齐,而且可以把较为复杂的运算,转化成简单的数组来表示。

提示:以下是本篇文章正文内容。
1、数组是什么
数组是一组相同类型元素的集合。
我们在C语言中有各种类型的元素,比如说int类型,float类型,double类型,long类型,当我们的元素类型是相同的时候,我们就可以把它们放在同一个集合里面,这个集合我们就称为数组。
数组我们又分为一维数组、二维数组和多维数组。下面开始为大家介绍一维数组和二维数组。
2、一维数组 2.1一维数组的创建 【创建形式】
type arr_name [const]; //type是指数组的元素类型 //arr_name是指数组的名字 //const是一个常量表达式,用来指定数组的大小

数组创建, [ ] 中要给一个常量才可以,不能使用变量。
【数组创建实例】
//代码1 int arr1[10]; //整型数组//代码2 int count = 10; int arr2[count]; //这种写法是错误的,因为数组里面只能放常量,也就是说它必须含有一个常量值//代码3 char arr3[10]; //字符数组 float arr4[1]; //单精度数组 double arr5[20]; //双精度数组 }

数组创建之后,我们需要初始化,那么怎么进行初始化呢?下面我们就来讲讲这个问题。
2.2一维数组的初始化
一维数组初始化就是给一维数组赋初值,作用就是申明的这个一维数组有了一个确定的值,从而可以得到具体应用。
一个数组申明后,如果没有赋值,那么只是分配了内存空间,没有具体的值,也可以说是空,其组成是“\0”也就是NULL,无法在实际中使用。
简单来说,数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
【数组初始化实例】
int arr[5]; //全局变量未初始化,默认是0int main() { int arr6[5]; //局部变量未初始化,默认值未随机值 int arr1[20] = { 1,2,3,4}; //不完全初始化,剩余的默认初始化为0 int arr2[] = { 1, 2, 3 }; char arr3[] = "abc"; //a,b,c,\0——有四个元素 char arr4[] = { 'a', 'b', 'c' }; //a,b,c——只有三个元素 char arr5[] = { 'a', 98, 'c' }; printf("%d\n", arr1[0]); return 0; }

在这里,我们可以打开vs2013编译器的监视窗口看看数组的值。
1、数组arr1[20]
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片
【注意】
数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
如上面代码中的数组char arr3[]; char arr4[]; char arr5[];
2.3一维数组的使用
1、对于数组的使用我们之前介绍了一个操作符: [ ] ,下标引用操作符。它其实就数组访问的操作符。
2、数组是使用下标来访问元素的,数组中第一个元素的下标为0。
3、数组的大小是可以计算的,用sizeof运算符计算,下面实例有讲。
【实例分析】
int main() { float sc[5] = { 0.0f,3.0f }; //结构体数组也可以创建 int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //创建数组并初始化 int i = 0; //计算数组元素个数 int sz = sizeof(arr) / sizeof(arr[0]); //sizeof(arr)表示整个数组大小,sizeof(arr[0])表示一个元素大小 for (i = 0; i < sz; i++) {printf("%d ", arr[i]); // 数组是使用下标来访问元素的 } return 0; }

玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

【总结】
  1. 数组是使用下标来访问的,下标是从0开始。
  2. 数组的大小可以通过计算得到。
2.4一维数组在内存中的存储
数组在内存中是连续存放的
【实例分析】
int main() { int arr[10] = { 0 }; //创建并初始化数组 int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); //计算数组大小 for (i = 0; i; ++i) {printf("&arr[%d] = %p\n", i, &arr[i]); //数组地址用%p打印,将数组地址逐个打印出来 } return 0; }

玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片
为什么会相差4?
因为我们定义的是一个整型数组,而一个整型元素是4个字节,所以数组地址打印出来相差4。
【总结】
随着数组下标的增长,元素的地址,有规律的递增。 数组在内存的存放是由低地址到高地址连续存放的。
3、二维数组 3.1二维数组的创建 【创建形式】
type arr_name [const1][const2]; //type是指数组的元素类型 //arr_name是指数组的名字 //const1、const2是一个常量表达式,用来指定数组的大小,表示有几行几列

【玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!】【创建实例】
//数组创建 int arr1[1][2]; //表示有1行2列 char arr2[3][4]; //表示有3行4列 double arr3[5][6]; //表示有5行6列

3.2二维数组的初始化 二维数组的初始化跟一维数组大同小异
int main() { int arr1[3][5] = { 1,2,3,4,5,6,7,8,9,10,11}; //三行五列,把一行放满之后再放第二行,依次类推,没得放之后,默认为0 int arr2[3][5] = { { 1, 2 }, { 3, 4 }, { 5,6} }; //每一行都看成一个一维数组,可以调试出来 int arr3[][5] = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; //二维数组的列不能省略,行可以省略,基于初始化的前提,不初始化不能省略 char ch1[4][6] = { 'a','b'}; char ch2[4][6] = { { ' a' }, { 'b' } }; char ch3[4][6] = { "abc","def","qwe" }; //四行六列 double d[4][7]; return 0; }

【分析】
数组arr1
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

【注意】
1、二维数组,放多少行没有所谓,因为默认是往前递增,但是省略列的话,就不知道一行放多少个元素了
2、可以认为二维数组有多少个元素,每个元素就是一个一维数组
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

3.3 二维数组的使用
二维数组的访问也是通过下标的形式进行的
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

3.4 二维数组在内存中的存储 那么二维数组在内存中的存储是不是也是跟一维数组一样的呢?
我们来打印一下:
int main() { int arr[3][5] = { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8, 9, 0 } }; int i = 0; for (i = 0; i < 3; i++)//0-2 {int j = 0; for (j = 0; j < 5; j++)//0-4 {printf("&arr[%d][%d]= %p\n",i,j,&arr[i][j]); } } return 0; }

玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片
【总结】
二维数组在内存中也是连续存储的
4、数组越界
前提: 数组的下标是有范围限制的。
1、数组的下规定是从0开始的,如果输入有n个元素,最后一个元素的下标就是n-1。
2、数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
3、C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查
【实例分析】
比如数组定义时有十个元素,那么a[0] – a[9] 分别对应相应的元素,在程序中如果使用了a[10]那么就超出了原来的数组定义的范围,这就是数组下标越界。
玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

【注意】
这里编译并没有报错,但是程序确实错的,所以在定义数组的时候,我们要千万小心。二维数组的行和列也可能存在越界。
5、数组名的探讨
一般来说数组名是首元素的地址 有两个例外
1、sizeof(数组名),这里的数组名表示整个数组,sizeof(数组名),计算的是整个数组的大小
2、&数组名,这里的数组名表示整个数组,取出的是数组的地址
【实例分析】
int main() { int arr[10] = { 1, 2, 3, 4, 5 }; printf("%p\n", arr); printf("%p\n", &arr[0]); printf("%p\n", &arr); //数值一样,但意义不同,前两个是首元素地址,第三个是数组的地址,虽然看起来值一样,意义不同 printf("---------------"); printf("%p\n", arr+1); printf("%p\n", &arr[0]+1); printf("%p\n", &arr+1); //前两个值依旧一样,但最后一个跟前两个差了40,因为数组是个元素,一个元素是一个整型,10个就是40个字节 //最后一个,跳过整个数组,前两个跳过一个元素 //数组的地址,影响的是整个数组,数组首元素的地址影响的是数组的元素 return 0; }

玩转C语言系列|【C语言】玩转数组——关于数组,你需要知道的秘密!
文章图片

1、前两个值依旧一样,但最后一个跟前两个差了40,因为数组是个元素,一个元素是一个整型,10个就是40个字节
2、最后一个,跳过整个数组,前两个跳过一个元素
3、数组的地址,影响的是整个数组,数组首元素的地址影响的是数组的元素
最后 以上内容是通过本人学习的理解和网上资料的整理梳理出来的数组的一些内容,有错漏之处,还请各位多多包涵与指出,共同进步,共同成长!

    推荐阅读