文章目录

  • 一、数组的基本概念
  • 二、一维数组
    • 2.1 一维数组的定义
    • 2.2 一维数组初始化
    • 2.3 一维数组的引用
  • 三、二维数组
    • 3.1 二维数组的定义
    • 3.2 二维数组初始化
    • 3.3 二维数组的引用
  • 四、C语言数组是静态的,不能插入或删除元素
  • 五、C语言数组的越界和溢出
    • 5.1 数组越界
    • 5.2 数组溢出

2018年9月1日,中国女排在2018年亚运会上3:0战胜了泰国女排,夺得了冠军,此时,阿里巴巴董事长主席马云见证了中国女排夺冠的辉煌一刻。同时马云承诺,要帮中国女排姑娘们清理购物车。本示例就来模拟列出某女孩的购物车清单,具体代码如下所示:

从代码中可以看到,图中被框出来的部分 长相类似 都是一个 标识符一个中括号([]) 箭头的另一端写着两个大字――数组,接下来我们简单的介绍一下数组的成分。

  1. DailyUse、Makeup、Sports、Health:即标识符。它们就是按照命名标识符规则定义的标识符,是程序员DIY定义的:
  2. []:即中括号。他的作用就是扩住数组的长度,中括号中间写的是数组的长度。
  3. 100、50、200、i等:即数组的长度。表示定义这个数组的长度。

根据上述,数组的形式就类似 a[10],没错,这是数组的形式之一,接下来我们详细介绍本章内容――数组,了解数组的作用,如何定义数组、初始化数组以及使用数组。

一、数组的基本概念

在某女孩的购物车清单实例中可以看到:

char DailyUse[50] = {"纸抽,纸巾,收纳箱,水杯,垃圾袋,剪刀,挂钩,拖鞋,小闹钟"};

这行代码中,DailyUse[50] 表示多个字符类型的变量,可以使用同一个名字 DailyUse,从而组成的集合,它就是一个数组。我们都知道,要想把数据放到内存中,就需要先分配内存,要想放入4个整型数据,就得分配4个int类型的内存空间,例如:

int arr[4];

这样我们就给分配了4个int型的内存空间,共计占4×4=16个字节,并为它们起了一个名字arr。我们把这样的一组数据的集合,叫做 数组(Array); 它所包含的每一个数据叫做 数组元素(Element); 所包含的数据的个数称为 数组长度(Length), 例如 int arr[4]; 就定义了一个长度为4的整型数组,名字是arr。数组中的每个元素都有一个序号,这个序号从 0 开始,而不是从我们熟悉的1开始,称为 下标(Index)。

二、一维数组

一维数组就像12个月,我们可以将12月起同一个名字month,1月~12月就是数组month的元素,示意图如下图所示:

2.1 一维数组的定义

一维数组是用于存储一维数组中数据的集合,它的一般形式如下:

类型说明符 数组标识符[常量表达式];// ①: 类型说明符表示数组中的所有元素类型// ②: 数组标识符表示该数组型变量的名称,命名规则与变量名一致// ③: 常量表达式定义了数组中存放的数据元素的个数,即数组长度。例如cArray[10],10表示数组中有10个元素,下标从0开始,到9结束

示例:

//1.定义一个长度为10的字符型数组//char为数组元素的类型,而cArray表示的是数组变量名,括号中的10表示的是数组中包含的元素个数char cArray[10];//2.定义一个长度为5的整型数组int number[5];//3.定义一个长度为20的浮点型数组float f[20];

定义数组还有以下几点注意事项:

同一个数组,数组的所有元素的数据类型都是相同的
数组名的书写规则应按照标识符的规定定义
允许在同一个类型说明中,说明多个数组和多个变量

int i,j,k,n,m1[10],m2[20];

方括号中常量表达式表示数组元素的个数,如number[5]表示数组number有5个元素。但是其下标从0开始计算。因此5个元素分别为:

int number[5];number[0];number[1];number[2];number[3];number[4];

访问数组元素时,下标的取值范围为 0≤index<length 过大或过小都会越界,导致数组溢出,发生不可预测的情况,我们将在后续小节重点讨论,请大家务必要引起注意。

数组名不能与其它变量名相同。如:

int cArray; float cArray[10]; //错误

数组长度 length 最好是整数或者常量表达式,例如 10、20*4 等,这样在所有编译器下都能运行通过;如果 length 中包含了变量,例如 n、4*m 等,在某些编译器下就会报错,我们将在后续小节专门讨论这点。

#define AI 3 //定义符号常量int cArray[1+2]; //定义数组int number[8+AI]; //定义数组// 不建议:int i=5;int number[i];

2.2 一维数组初始化

给一维数组初始化就是给一维数组赋予初值。初始化的一般格式如下:

类型说明符 数组标识符[常量表达式]={1,2,3,4};//{}中间的各个值就是各元素的初值,各值之间用英文逗号隔开,定义结束后,用英文分号结束此句代码。例如:int number[5]={1,2,3,4,5};// number[0]=1, number[1]=2, number[2]=3, number[3]=4, number[4]=5

在C语言中,对一维数组的初始化可以用以下几种方法实现:

//1.在定义数组时直接对数组元素赋初值,例如:int iArray[8]={1,2,3,4,5,6,7,8};//经过上面的定义和初始化之后,数组中的元素//iArray[0]=1,iArray[1]=2,iArray[2]=3,iArray[3]=4,iArray[4]=5,iArray[5]=6,iArray[6]=7,iArray[7]=8//2.只给一部分元素赋值,未赋值的部分元素值为0int iArray[8]={1,2,3};//经过上面的定义和初始化之后,数组中的元素//iArray[0]=1,iArray[1]=2,iArray[2]=3,iArray[3]=0,iArray[4]=0,iArray[5]=0,iArray[6]=0,iArray[7]=0//3.在对全部数组元素赋初值时可以不指定数组长度int iArray[]={1,2,3,4};//4.先定义数组再给数组赋值int a[4];a[0]=120;a[1]=1345;a[2]=1700;a[3]=122;

2.3 一维数组的引用

数组定义完成后就要使用该数组,可以通过引用数组元素的方式使用该数组中的元素。数组元素表示的一般形式如下:

数组标识符[下标]

其中的下标可以是整型常量和整型表达式。如果为小数时,C编译器会自动取整,例如:

这段代码的第2行是引用数组,其中 iArray 是数组变量的名称,2为数组的下标。前面介绍过数组的下标是从0开始的,也就是说下标为0表示的是第一个数组元素。因此第3个元素下标是2,所以这句引用的是数组 iArray 的第3个元素。在C语言中只能逐个地使用下标变量,而不能一次引用整个数组。例如,逐个输出数组元素,代码如下:

这段代码实现的功能是输出数组 iArray 的各个元素,使用 iArray[i] 引用数组是合法的。但是:

这段代码也是想要输出数组各元素,但是它不是逐个输出,而是用一条语句输出数组,这样就是不合法的,不能输出数组各个元素值。示例: 使用一维数组输出某高中班级前5名的总成绩,代码如下:

/*================================================================* Copyright (C) 2023 AmoXiang All rights reserved.* * 文件名称:01-array.c* 创 建 者:AmoXiang* 创建日期:2023年10月10日 15:32:08* 描述:*================================================================*/#include  //包含头文件int main(){ //主函数int grade[5]; //定义数组int i = 0, j = 0;// 从控制台读取用户输入printf("请输入前5名各学生成绩: \n");for(;i<5;i++){ //输入学生成绩printf("第%d名成绩: ", i + 1);scanf("%d", &grade[i]); //注意取地址符&,不要遗忘}// 依次输出数组元素printf("前5名各学生成绩如下: \n");for(;j<5;j++){printf("第%d个成绩是: %d\n", j+1, grade[j]);}return 0;}

程序运行结果如下图所示:

三、二维数组

在第二小节讲解了一维数组,一维数组的下标只有一个,而如果下标是两个呢?在C语言中,将下标是两个的称为二维数组,例如 Array[m][n] 表示第m行第n列。例如,一个书柜布局如下图所示,利用书柜的行、列能够快速找到书的位置,而二维数组就类似行和列。

3.1 二维数组的定义

二维数组的声明与一维数组类似,一般形式如下:

数据类型 数组名[常量表达式1][常量表达式2];// "常量表达式1"被称为行下标 "常量表达式2" 被称为列下标// 如果有二维数组array[n][m],则二维数组的下标取值范围如下:// 行下标的取值范围0~n-1 列下标的取值范围0~m-1 二维数组的最大下标元素是array[n-1][m-1]

例如,定义一个3行5列的整型数组,代码如下:

int array[3][5];//这一行代码说明了一个3行5列的数组,数组名为array,其下标变量的类型为整型。//该数组的下标变量共有3×5个,即array[0][0] array[0][1] array[0][2] array[0][3] array[0][4]array[1][0] array[1][1] array[1][2] array[1][3] array[1][4]array[2][0] array[2][1] array[2][2] array[2][3] array[2][4]

在C语言中,二维数组是按行排列的,即按行顺次存放,先存放 array[0] 行,再存放 array[1] 行。每行中的5个元素,也是依次存放。

3.2 二维数组初始化

在C语言中,对二维数组的初始化可以用以下几种方法实现:

//1.可以将所有数据写在一个大括号内,按照数组元素排列顺序对元素赋值int array[2][2]={1,2,3,4};//表示的二维数组形式如下:1 2 3 4 // 即array[0][0]的值是1,array[0][1]的值是2,array[1][0]的值是3,array[1][1]的值是4//2.在为所有元素赋初值时,可以省略行下标,但是不能省略列下标int array[][3]={1,2,3,4,5,6};//系统会根据数据的个数进行分配,一共有6个数据,而数组每行分为3列,当然可以确定数组为2行 形式:1 2 34 5 6//3.也可以分行给数组元素赋值int array[2][3]={{1,2,3},{4,5,6}};//4.在分行赋值时,可以只对部分元素赋值,未被赋值的元素系统默认的值为0int array[2][3]={{1,2},{4,5}};//5.二维数组也可以直接对数组元素赋值 这种赋值的方式就是使用数组引用的数组中的元素int array[2][2];array[0][0] = 1;array[0][1] = 2; array[1][0] = 1;array[1][1] = 2;

3.3 二维数组的引用

二维数组元素的引用一般形式为:

//不管是行下标还是列下标,其索引都是从0开始的数组名[行下标][列下标]; //说明:二维数组的下标可以是整型常量或整型表达式int array[2][2]={{5,2},{5,4}};//定义二维数组array[1][1];//引用二维数组元素

例如:用二维数组求下表中分科的平均成绩。

具体代码如下:

/*================================================================* Copyright (C) 2023 AmoXiang All rights reserved.* * 文件名称:02-array.c* 创 建 者:AmoXiang* 创建日期:2023年10月10日 17:09:13* 描述:*================================================================*/#include int main() {int k, l, arr[3][5]; // 定义变量和二维数组int score = 0, course[3];//定义变量和二维数组printf("请输入成绩: \n");for (k = 0; k < 3; ++k) { //遍历二维数组行for (l = 0; l < 5; ++l) { //遍历二维数组列printf("array[%d][%d]=", k, l);scanf("%d", &arr[k][l]);score += arr[k][l]; //计算成绩}course[k] = score / 5; //求每科的平均成绩score = 0;//重新赋值}printf("数学的平均成绩是(取整数): %d\n", course[0]);printf("语文的平均成绩是(取整数): %d\n", course[1]);printf("英语的平均成绩是(取整数): %d\n", course[2]);return 0;}

程序运行结果如下图所示:

四、C语言数组是静态的,不能插入或删除元素

在C语言中,数组一旦被定义后,占用的内存空间就是固定的,容量就是不可改变的,既不能在任何位置插入元素,也不能在任何位置删除元素,只能读取和修改元素,我们将这样的数组称为 静态数组。 反过来说,如果数组在定义后可以改变容量,允许在任意位置插入或者删除元素,那么这样的数组称为 动态数组。 Python,JavaScript 等解释型的脚本语言一般都支持动态数组,而 C,C++,Java 等编译型的语言一般不支持动态数组。总之,C语言中的数组是静态的,一旦定义后长度就不能改变了,大家要注意这一点,不要尝试去插入或删除元素。如果由于项目要求,必须要在数组中插入或者删除元素,只能再造一个新数组!

C语言数组为什么是静态的” />五、C语言数组的越界和溢出

5.1 数组越界

C语言数组是静态的,不能自动扩容,当下标小于零或大于等于数组长度时,就发生了 越界(Out Of Bounds), 访问到数组以外的内存。如果下标小于零,就会发生 下限越界(Off Normal Lower); 如果下标大于等于数组长度,就会发生 上限越界(Off Normal Upper)。

C语言为了提高效率,保证操作的灵活性,并不会对越界行为进行检查,即使越界了,也能够正常编译,只有在运行期间才可能会发生问题。请看下面的代码:

/*================================================================* Copyright (C) 2023 AmoXiang All rights reserved.* * 文件名称:04-array.c* 创 建 者:AmoXiang* 创建日期:2023年10月11日 10:30:55* 描述:*================================================================*/#include int main() {int a[3] = {101, 201, 301}, i;for (i = -2; i <= 4; i++) {printf("a[%d]=%d\n", i, a[i]);}return 0;}

程序运行结果如下图所示:

越界访问的数组元素的值都是不确定的,没有实际的含义,因为数组之外的内存我们并不知道是什么,可能是其它变量的值,可能是函数参数,可能是一个地址,这些都是不可控的。

由于C语言的 放任 我们访问数组时必须非常小心,要确保不会发生越界。每个C语言程序员的生涯中都遇到过越界错误,我拿项上人头作保证,所以千万不要大意,因为越界错误有时候不容易发现,也不容易复现。当发生数组越界时,如果我们对该内存有使用权限,那么程序将正常运行,但会出现不可控的结果(如上例所示);如果我们对该内存没有使用权限,或者该内存压根就没有被分配,那么程序将会崩溃。

5.2 数组溢出

当赋予数组的元素个数超过数组长度时,就会发生 溢出(Overflow)。 如下所示:

//数组长度为3,初始化时却赋予5个元素,超出了数组容量,所以只能保存前3个元素,后面的元素被丢弃int a[3] = {1, 2, 3, 4, 5};

一般情况下数组溢出不会有什么问题,顶多是丢失多余的元素。但是当以字符串的形式输出字符数组时,就会产生不可控的情况,请看下面的代码:

/*================================================================* Copyright (C) 2023 AmoXiang All rights reserved.* * 文件名称:04-array.c* 创 建 者:AmoXiang* 创建日期:2023年10月11日 10:30:55* 描述:*================================================================*/#include int main(){char str[5] = "https://blog.csdn.net/xw1680" />;puts(str);return 0;}

程序运行结果如下图所示:

字符串的长度大于数组长度,数组只能容纳字符串的前面一部分,也就是 "https" 即使编译器在最后添加了 '\0' 它也保存不到数组里面,所以 printf() 扫描数组时不会遇到结束符 '\0' 只能继续向后扫描。而后面内存中的数据我们不知道是什么,字符能否识别,何时遇到 '\0' 这些都是不确定的。当字符无法识别时,就会出现乱码,显示奇怪的字符。由此可见,在用字符串给字符数组赋值时,要保证数组长度大于字符串长度,以容纳结束符 '\0'

至此今天的学习就到此结束了,笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习C语言的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!


好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 点赞评论收藏 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!