C语言数组这些知识,你真的会了吗?(万字详细总结,让你快速掌握)

✅作者简介:大家好,我是小杨
📃个人主页:「小杨」的csdn博客
🔥系列专栏:小杨带你玩转C语言【初阶】
🐳希望大家多多支持🥰一起进步呀!


在这里插入图片描述


前言:大家好呀!我是小杨。小杨把C语言中的数组做了一个总结,希望在方便自己复习的同时也能够帮助到大家。 文章很长建议先收藏再看,防止下次想看看就找不到啦,哈哈哈😃😃😃

知识点
✨数组
  🚀1.1,数组的定义
  🚀1.2,数组的分类

✨一维数组
🚀2.1,一维数组的定义
      🔭2.1.1,一维数组的一般形式
      🔭2.1.2,一维数组的示例说明
  🚀2.2,一维数组的引用
      🔭2.2.1,一维数组的引用一般形式
      🔭2.2.2,一维数组的引用注意说明
  🚀2.3,一维数组的初始化
      🔭2.3.1,一维数组的初始化一般形式
      🔭2.3.2,一维数组的初始化示例说明
  🚀2.4,一维数组的使用
  🚀2.5,一维数组在内存中的存储

✨二维数组
🚀3.1,二维数组的定义
      🔭3.1.1,二维数组的一般形式
      🔭3.1.2,二维数组的示例说明
  🚀3.2,二维数组的引用
      🔭2.2.1,二维数组的引用一般形式
      🔭3.2.2,二维数组的引用注意说明
  🚀3.3,二维数组的初始化
      🔭3.3.1,二维数组的初始化一般形式
      🔭3.3.2,二维数组的初始化示例说明
  🚀3.4,二维数组的使用
  🚀3.4,二维数组在内存中的存储

✨字符数组
🚀4.1,字符数组的定义
      🔭4.1.1,字符数组的一般形式
      🔭4.1.2,字符数组的示例说明
  🚀4.2,字符数组的引用
      🔭4.2.1,字符数组的引用一般形式
      🔭4.2.2,字符数组的引用注意说明
  🚀4.3,字符数组的初始化
      🔭4.3.1,字符数组的初始化一般形式
      🔭4.3.2,字符数组的初始化示例说明
  🚀4.4,字符数组的使用
  🚀4.4,字符数组在内存中的存储

✨扩展:数组名
  🚀5.1,一维数组的数组名
      🔭5.1.1,sizeof(数组名)
      🔭5.1.2,&数组名
  🚀5.2,二维数组的数组名
      🔭5.2.1,sizeof(数组名)
      🔭5.2.2,&数组名
      🔭5.2.3,二维数组的行列数


✨数组
🚀1.1,数组的定义

数组是由基本数据类型按照一定规则组成的,称其为构造数据类型。

构造数据类型包括数组,结构体,共用体等,使用构造数据类型可以求解更为复杂的问题。

数组是最基本的构造类型,是相同类型数据的有序集合。

数组中的元素在内存中连续存放,用数组名和下标可以唯一地确定数组元素。

🚀1.2,数组的分类

有序数组指的是数组中的每一个元素在集合中都是按序排列的,排列的位置用其下标来表示。

带有一个下标的数组称为一维数组,带有两个下标的数组称为二维数组,带有多个下标的数组称为多维数组。


🚉由此返回目录


✨一维数组
🚀2.1,一维数组的定义
🔭2.1.1,一维数组的一般形式

一维数组定义的一般形式

类型名 数组名 [常量表达式]
🔭2.1.2,一维数组的示例说明
int a[6];

说明:

(1)定义了一个整型一维数组,数组名为a,含有6个元素。

(2)数组名后是用方括号[]括起来的“常量表达式”。

注意:不能使用圆括号()和花括号{}。

int k(10);//不合法
int l{10};//不合法

(3)方括号中的“常量表达式”,用于表示数组元素的个数,即数组的长度。

C语言规定,数组元素下标是从0开始,不能为负数:而下标的最大值由”常量表达式“的值减1确定。

注意:C语言在编译过程中不检查数组元素的下标是否越界,若数组下标越界,则会造成不可预知的后果。

(4)常量表达式可以是整型常量或者符号常量,不包含变量。也就是不允许用变量来对数组大小进行定义。

int i=10;
int a[i];
//这种定义不合法
#define N 15
int a[N];
//这种定义合法

(5)和普通变量一样,定义数组时系统会为每个数组元分配存储单元。同一数组的数组元素在内存中占用的存储单元是连续的。

int a[10];
//定义一个有10个整型元素的数组a
char ch[15];
//定义一个有15个字符型元素的数组ch
float 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。

static int a[6];
//相当于:
static int 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>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

代码调试:

在这里插入图片描述

输出结果:

在这里插入图片描述


🚀2.5,一维数组在内存中的储存

代码:

#include<stdio.h>
int main()
{
	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]);
	}
	return 0;
}

输出结果:

在这里插入图片描述

仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。

由此可以得出结论:数组在内存中是连续存放的。

在这里插入图片描述


✈由此返回目录


✨二维数组
🚀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列
第04	   0	   013	   0	   022	   0	   031	   0	   0
  • 对各行中某一元素赋初值
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列
第01	   2     013	   0     020	   0     030	   0     0

🚀3.4,二维数组的使用

代码:

#include<stdio.h>
int main()
{
	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]);
		}
	}
	return 0;
}

代码调试:

在这里插入图片描述

输出结果:

在这里插入图片描述


🚀3.5,二维数组在内存中的存储

代码

#include<stdio.h>
int main()
{
	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]);
		}
	}
	return 0;
}

输出结果:

在这里插入图片描述

内存中的储存:

随着数组下标的增长,元素的地址,也在有规律的递增。

二维数组在内存中也是连续存储的。

在这里插入图片描述


🚉由此返回目录


✨字符数组
🚀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>
int main()
{
	char str[10] = { "CHINRESE" };
	for (int i = 0; i < 10; i++)
	{
		printf("%c ", str[i]);
	}
	return 0;
}

代码调试:

在这里插入图片描述

输出结果:

在这里插入图片描述


🚀4.5,字符数组在内存中的存储

代码:

#include<stdio.h>
int main()
{
	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]);
	}
	return 0;
}

输出结果:

在这里插入图片描述

内存中的储存:

随着数组下标的增长,元素的地址,也在有规律的递增。

字符数组在内存中是连续存储的。

在这里插入图片描述


🚉由此返回目录


✨扩展:数组名

数组名表示首元素的地址。
但是数组名不表示首元素的地址有2个例外:

  • sizeof(数组名)
  • &数组名

🚀5.1,一维数组的数组名
🔭5.1.1,sizeof(数组名)

代码:

#include<Stdio.h>
int main()
{
	int arr[10] = {0};
    int n = sizeof(arr);//40
	printf("%d\n", n);
	return 0;
}

输出结果:

在这里插入图片描述

结论:

sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。

🔭5.1.2,&数组名

代码:

#include<Stdio.h>
int main()
{
	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);
	return 0;
}

输出结果:

在这里插入图片描述

结论:&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。


🚀5.2,二维数组的数组名
🔭5.2.1,sizeof(数组名)

代码:

#include<Stdio.h>
int main()
{
	int arr[3][4] = {0};
    int n = sizeof(arr);//48
	printf("%d\n", n);
	return 0;
}

输出结果:

在这里插入图片描述

🔭5.2.2,&数组名

代码:

#include<Stdio.h>
int main()
{
	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);
	return 0;
}

输出结果:

在这里插入图片描述

分析:

在上述代码里,二维数组的首元素是一维数组arr[0],arr[0]+1为arr[1],因arr1[0]与arr[1]之间有4个数组元素,故arr[0]与arr[1]的地址相差16个字节。

在程序编译过程中,数组元素地址是以16进制的形式编译。

🔭5.2.3,二维数组行列数

代码:

#include<stdio.h>
int main()
{
	int arr[3][4] = { 0 };
	printf("%d\n", sizeof(arr) / sizeof(arr[0]));//求二维数组的行数
	printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));//求二维数组的列数
	return 0;
}

输出结果:

在这里插入图片描述

结论:

  • 二维数组的行数等于sizeof(数组名)/sizeof(二维数组首元素)

  • 二维数组的列数等于sizeof(二维数组首元素)/sizeof(一维数组首元素)


🚉由此返回目录


结语

小伙伴们,当你学到这里的时候,你们应该对数组部分的内容已经有了全新的认识吧!🥳🥳🥳后续小杨会给大家总结指针的内容,不断更新优质的内容来帮助大家,一起进步。加油,追梦人!让我们一起拥抱美好明天!🎆🎆🎆

在这里插入图片描述

  • 117
    点赞
  • 197
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 83
    评论
评论 83
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小杨MiManchi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值