大家好呀!我是小杨。小杨把C语言中的数组做了一个总结,希望在方便自己复习的同时也能够帮助到大家。 文章很长建议先收藏再看,防止下次想看看就找不到啦,哈哈哈😃😃😃
✨数组
🚀1.1,数组的定义
数组是由基本数据类型按照一定规则组成的,称其为构造数据类型。
构造数据类型包括数组,结构体,共用体等,使用构造数据类型可以求解更为复杂的问题。
数组是最基本的构造类型,是相同类型数据的有序集合。
数组中的元素在内存中连续存放,用数组名和下标可以唯一地确定数组元素。
🚀1.2,数组的分类
有序数组指的是数组中的每一个元素在集合中都是按序排列的,排列的位置用其下标来表示。
带有一个下标的数组称为一维数组,带有两个下标的数组称为二维数组,带有多个下标的数组称为多维数组。
✨一维数组
🚀2.1,一维数组的定义
🔭2.1.1,一维数组的一般形式
一维数组定义的一般形式
类型名 数组名 [常量表达式]
🔭2.1.2,一维数组的示例说明
int a[6];
说明:
(1)定义了一个整型一维数组,数组名为a,含有6个元素。
(2)数组名后是用方括号[]括起来的“常量表达式”。
注意:不能使用圆括号()和花括号{}。
intk(10);//不合法int l{10};//不合法
(3)方括号中的“常量表达式”,用于表示数组元素的个数,即数组的长度。
C语言规定,数组元素下标是从0开始,不能为负数:而下标的最大值由”常量表达式“的值减1确定。
注意:C语言在编译过程中不检查数组元素的下标是否越界,若数组下标越界,则会造成不可预知的后果。
(4)常量表达式可以是整型常量或者符号常量,不包含变量。也就是不允许用变量来对数组大小进行定义。
int i=10;int a[i];//这种定义不合法
#define N 15int a[N];//这种定义合法
(5)和普通变量一样,定义数组时系统会为每个数组元分配存储单元。同一数组的数组元素在内存中占用的存储单元是连续的。
int a[10];//定义一个有10个整型元素的数组achar ch[15];//定义一个有15个字符型元素的数组chfloat f[20];//定义一个有20个浮点型元素的数组f
(6)在一个定义语句中,可以有多个数组说明符,它们之间用用逗号隔开。
int a[10],b[10];
分别定义了名为a和b的数组,数组元素个数均为10。
🚀2.2,一维数组的引用
与简单变量不同的是,不能整体引用一个数组,只能引用数组中的某一个元素。
换而言之,在参与表达式运算时,数组只能以数组元素的形式出现。
🔭2.2.1,一维数组的引用一般形式
数组名 [下标]
注:下标必须是整型表达式。
a[3]=5;//将5赋值给数组元素a[3] a[2]=a[3]-a[a[3]-4];//将a[3]与a[1]之差赋值给数组元素a[2]
🔭2.2.2,一维数组的引用注意说明
- 因数组的定义和数组元素的引用都是用“数组名[常量表达式]”,故注意区分数组的定义和数组元素的引用。
- 定义数组时,方括号内的常量表达式代表数组长度,可以整型常量和符号常量,但不能是变量。
- 数组的长度在定义时必须指定,在程序中运行的过程中不能改变。
- 引用数组元素时,方括号内是表达式,代表下标,可以是变量,下标取值范围是[0,数组长度-1]。
🚀2.3,一维数组的初始化
和普通变量一样,在定义时可以对数组元素进行赋值,称为数组的初始化。
🔭2.3.1,一维数组的初始化一般形式
一维数组的初始化一般形式:
类型名 数组名[数组长度]={初值表};
🔭2.3.2,一维数组的初始化示例说明
int a[6]={1,2,3,4,5,6};//定义a数组的同时初始化
数组初始化后各元素分别为a[0]=1,a[1]=2,a[2]=3,a[3]=4,a[4]=5,a[5]=6。
说明:
1,数组元素的初值依次写在一对花括号内,数组之间用逗号分隔。当初值的个数与数组长度相同时,初始化可以省略数组长度。
int a[6]={1,2,3,4,5,6};//可以等价为:int a[]={1,2,3,4,5,6};
注意:若定义数组时。没有对其初始化,则数组长度不能省略。
2,静态存储的数组在定义时如果没有初始化,系统会自动给数组的所有元素赋值为0。
staticint a[6];//相当于:staticint a[6]={0,0,0,0,0,0};
3,动态存储的数组在定义时如果没有初始化,则与“未初始化的变量,其值是不确定的”一样,其元素的值不确定。
int a[6];//此时a[0]~a[5]的值未知,不确定
4,可以只给数组的前几个元素赋初值,其余元素的初值系统自动赋值为0。
int a[6]={1,2,3};//只对前3个元素赋初值,其余元素赋值为0
注意:若只对数组部分元素赋初值,因初值的个数与数组长度不相同,数组的数组长度不能省略。
int a[]={1,2,3}; //系统会认为a数组只有3个数组元素,而不是6个数组元素
5,若一个数组中的每个元素的值均为0,可以简写成:
//正确写法int a[6]={0};//错误写法int a[6]=0;
6,若初值个数大于数组的长度,则系统会产生编译错误。
int a[6]={1,2,3,4,5,6,7};//系统会编译错误
7,初值表中只能是常量,不能为变量,即使是赋值的变量也不可以。
int n=10; a[3]={n};//错误写法
🚀2.4,一维数组的使用
代码:
#include<stdio.h>intmain(){int arr1[10]={1,2,3,4,5,6,7,8,9,10};for(int i =0; i <10; i++){printf("%d ", arr1[i]);}return0;}
代码调试:
输出结果:
🚀2.5,一维数组在内存中的储存
代码:
#include<stdio.h>intmain(){int arr1[10]={1,2,3,4,5,6,7,8,9,10};for(int i =0; i <10; i++){printf("arr1[%d]=%p\n",i,&arr1[i]);}return0;}
输出结果:
仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。
由此可以得出结论:数组在内存中是连续存放的。
✨二维数组
🚀3.1,二维数组的定义
🔭3.1.1,二维数组的一般形式
类型名 数组名 [常量表达式1][常量表达式2]
- 与一维数组相比,二维数组定义添加一个常量表达式,其他的都一样。
- 常量表达式1表示数组第一维的长度(行数),常量表达式2表示数组第二维的长度(列数)。
- 二维数组的数据结构是个二维表,相当于数学中的一个矩阵,可以将其看成若干行,若干列组成。
🔭3.1.2,二维数组的注意说明
int a[4][3];
定义数组a为4*3(4行,3列)的二维数组,其元素及逻辑结构如下:
第0列 第1列 第2列
第0行 a[0][0] a[0][1] a[0][2]
第1行 a[1][0] a[1][1] a[1][2]
第2行 a[2][0] a[2][1] a[2][2]
第3行 a[3][0] a[3][1] a[3][2]
1,二维数组a的数组元素行下标为0~ 3,列下标为0~2,共12个元素。
2,与一维数组一样,在使用二维数组时要特别注意数组元素下标是否越界。
说明:
(1)表示行数和列数的常量表达式必须在两个中括号内,不能合并写在一个中括号内。
(2)二维数组(包括多维数组)在内存中是按行存放,即在内存中先存放第一行的元素,再存放第二行的元素,…,以此方式存放。
(3)对多维数组可以看成是其元素也是数组的数组。
int a[4][3];//该二维数组可以被看成是a[0],a[1],a[2],a[3]四个一维数组构成的数组。//a[0]的数组元素有:a[0][0],a[0][1],a[0][2]//a[1]的数组元素有:a[1][0],a[1][1],a[1][2]//a[2]的数组元素有:a[2][0],a[2][1],a[2][2]//a[3]的数组元素有:a[3][0],a[3][1],a[3][2]
这种逐步分解,降低维数的方法对于理解多维数组的存储方式,初始化以及指针有很大的帮助。
🚀3.2,二维数组的引用
和一维数组一样,二维数组被引用的也是它的元素,而不是它的名称(名称表示二维数组第一个元素的首地址)。
🔭3.2.1,二维数组的引用一般形式
二维数组的应用一般形式:
数组名[行下标][列下标]
🔭3.1.2,二维数组的示例说明
二维数组的元素与一维数组元素一样可以参加表达式运算。
b[1][0]=a[1][0]*10+5;
🚀3.3,二维数组的初始化
二维数组与一维数组一样,可以在说明时进行初始化。二维数组的初始化要特别注意各个变量数据的排列顺序,这个排列顺序与数组各元素在内存中的存储顺序完全一致。
🔭3.3.1,二维数组的初始化一般形式
二维数组初始化的一般形式:
类型名 数组名[行数][列数]={初值表};
🔭3.3.2,二维数组的初始化示例说明
(1)按行给二维数组赋初值。
int a[3][4]={{1,2,3,4},{2,3,4,5},{3,4,5,6}};
这种初始化比较直观,二维数组的行数等于初值表中大括号的对数。即第一对大括号内的数据赋值给第一行的元素,第二对括号内的数据赋值给第二行的元素,…,逐行赋值。
(2)可以将所有数据放置在一个大括号内,按数组元素排列的顺序赋初值。
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
效果同上,但按行的赋值方法较好,一个大括号对应一个一行,清晰明了。而这种方法,若数据过多,容易遗漏,不易检查。、
(3)对二维数组部分元素赋初值。
- 对各行首列元素赋初值
int a[4][3]={{4},{3},{2},{1}};
作用是只对各行第一列的元素赋初值,其余元素值自动为0.赋初值后数组各元素为:
第0列 第1列 第2列 第0行 400 第1行 300 第2行 200 第3行 100
- 对各行中某一元素赋初值
int a[4][3]={{1},{2,3},{3,4,5},{6}};
赋初值后数组各元素为:
第0列 第1列 第2列 第0行 1 0 0 第1行 2 3 0 第2行 3 4 5 第3行 6 0 0
- 对某几行元素赋初值
int a[4][3]={{1,2},{3}};
赋初值后数组各元素为:
第0列 第1列 第2列 第0行 120 第1行 300 第2行 000 第3行 000
🚀3.4,二维数组的使用
代码:
#include<stdio.h>intmain(){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] = %d\n", i, j, arr[i][j]);}}return0;}
代码调试:
输出结果:
🚀3.5,二维数组在内存中的存储
代码:
#include<stdio.h>intmain(){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]);}}return0;}
输出结果:
内存中的储存:
随着数组下标的增长,元素的地址,也在有规律的递增。
二维数组在内存中也是连续存储的。
✨字符数组
🚀4.1,字符数组的定义
与整型数组的数组元素是一个整数,实数数组的元素是一个实数一样,字符数组的元素是一个字符。
🔭4.1.1,字符数组的一般形式
字符数组也分为一维字符数组和二维字符数组。
(1)一维字符数组的一般形式:
char 数组名[常量表达式];
(2)二维字符数组的一般形式:
char 数组名[常量表达式1][常量表达式2];
🔭4.1.2,字符数组的示例说明
(1)一维字符数组的示例:
char str[5];
(2)二维字符数组的示例:
char str[5][5];
🚀4.2,字符数组的引用
🔭4.2.1,字符数组的引用一般形式
(1)一维字符数组的引用一般形式:
数组名[下标]
(1)二维字符数组的引用一般形式:
数组名[行数][列数]
🔭3.1.2,字符数组的示例说明
(1)一维字符数组的引用示例:
str[1]
(1)二维字符数组的引用示例:
str[2][2]
🚀4.3,字符数组的初始化
🔭4.3.1,字符数组的初始化一般形式
(1)一维字符数组初始化一般形式:
char 数组名[常量表达式]={初值表};
(2)二维字符数组初始化一般形式:
char 数组名[常量表达式1][常量表达式2]={初值表};
🔭4.3.2,字符数组的初始化示例说明
(1)一维字符数组初始化示例:
char str[5]={'h','e','l','l','o'};
(2)二维字符数组初始化示例:
char str[4][4]={{'b','i','g','l'},{'a','s','d','f'},{'g','j','k','e'},{'r','t','u','k'}};
说明:
(1)若初值表中的初值个数大于字符数组的长度,则会出现编译错误。
(2)若初值表中的初值个数小于字符数组的长度,则多余的字符元素的初值默认为0。
(3)若初值表中的初值个数等于字符数组的长度,可以在定义时省略数组的长度,系统编译会根据初值的个数确定数组的长度。
(4)允许用字符串常量对字符数组进行初始化。
char str[5]={'C','H','I','N','A'};char str[]={'C','H','I','N','A'};char str[]={"CHINA"};char str[]="CHINA";//这四种初始化语句等价
(5)不能在定义数组后,对数组名进行赋初值。
char str[5]; str[5]="hello";//不合法char str[5]; str ="hello";//不合法
(6)若字符数组在定义时未进行初始化,则数组各元素的初值是不确定的,与整型数组同理。
(7)二维字符数组的初始化与一维字符数组的初始化方法相类似。
(8)字符’\0’代表整数0,也就是ASCII码为0的字符,但’\0’不是字符’0’,'0’的ASCII码为48。
🚀4.4,字符数组的使用
代码:
#include<stdio.h>intmain(){char str[10]={"CHINRESE"};for(int i =0; i <10; i++){printf("%c ", str[i]);}return0;}
代码调试:
输出结果:
🚀4.5,字符数组在内存中的存储
代码:
#include<stdio.h>intmain(){char str[8]={"CHINRESE"};int sz =sizeof(str)/sizeof(str[0]);for(int i =0; i < sz; i++){printf("%c = %p\n", str[i],&str[i]);}return0;}
输出结果:
内存中的储存:
随着数组下标的增长,元素的地址,也在有规律的递增。
字符数组在内存中是连续存储的。
✨扩展:数组名
数组名表示首元素的地址。
但是数组名不表示首元素的地址有2个例外:
- sizeof(数组名)
- &数组名
🚀5.1,一维数组的数组名
🔭5.1.1,sizeof(数组名)
代码:
#include<Stdio.h>intmain(){int arr[10]={0};int n =sizeof(arr);//40printf("%d\n", n);return0;}
输出结果:
结论:
sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。
🔭5.1.2,&数组名
代码:
#include<Stdio.h>intmain(){int arr[10]={0};printf("%p\n", arr);//arr就是首元素的地址printf("%p\n", arr+1);printf("----------------------\n");printf("%p\n",&arr[0]);//&arr[0]是首元素的地址printf("%p\n",&arr[0]+1);printf("----------------------\n");printf("%p\n",&arr);//&arr数组的地址printf("%p\n",&arr+1);return0;}
输出结果:
结论:&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
🚀5.2,二维数组的数组名
🔭5.2.1,sizeof(数组名)
代码:
#include<Stdio.h>intmain(){int arr[3][4]={0};int n =sizeof(arr);//48printf("%d\n", n);return0;}
输出结果:
🔭5.2.2,&数组名
代码:
#include<Stdio.h>intmain(){int arr[3][4]={0};printf("%p\n", arr);//arr就是首元素的地址printf("%p\n", arr +1);printf("----------------------\n");printf("%p\n",&arr[0]);//&arr[0]是首元素的地址printf("%p\n",&arr[0]+1);printf("----------------------\n");printf("%p\n",&arr);//&arr数组的地址printf("%p\n",&arr +1);return0;}
输出结果:
分析:
在上述代码里,二维数组的首元素是一维数组arr[0],arr[0]+1为arr[1],因arr1[0]与arr[1]之间有4个数组元素,故arr[0]与arr[1]的地址相差16个字节。
在程序编译过程中,数组元素地址是以16进制的形式编译。
🔭5.2.3,二维数组行列数
代码:
#include<stdio.h>intmain(){int arr[3][4]={0};printf("%d\n",sizeof(arr)/sizeof(arr[0]));//求二维数组的行数printf("%d\n",sizeof(arr[0])/sizeof(arr[0][0]));//求二维数组的列数return0;}
输出结果:
结论:
- 二维数组的行数等于sizeof(数组名)/sizeof(二维数组首元素)
- 二维数组的列数等于sizeof(二维数组首元素)/sizeof(一维数组首元素)
结语
小伙伴们,当你学到这里的时候,你们应该对数组部分的内容已经有了全新的认识吧!🥳🥳🥳后续小杨会给大家总结指针的内容,不断更新优质的内容来帮助大家,一起进步。加油,追梦人!让我们一起拥抱美好明天!🎆🎆🎆
版权归原作者 小杨爱编程☆ 所有, 如有侵权,请联系我们删除。