文章目录
- 前言
- 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];//全局变量未初始化,默认是0
int 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]
【注意】
数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
如上面代码中的数组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;
}
【总结】
- 数组是使用下标来访问的,下标是从0开始。
- 数组的大小可以通过计算得到。
2.4一维数组在内存中的存储
数组在内存中是连续存放的
【实例分析】
int main()
{
int arr[10] = { 0 };//创建并初始化数组
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组大小
for (i = 0; i<sz; ++i)
{
printf("&arr[%d] = %p\n", i, &arr[i]);
//数组地址用%p打印,将数组地址逐个打印出来
}
return 0;
}
为什么会相差4?
因为我们定义的是一个整型数组,而一个整型元素是4个字节,所以数组地址打印出来相差4。
【总结】
随着数组下标的增长,元素的地址,有规律的递增。 数组在内存的存放是由低地址到高地址连续存放的。
3、二维数组
3.1二维数组的创建
【创建形式】
type arr_name [const1][const2];
//type是指数组的元素类型
//arr_name是指数组的名字
//const1、const2是一个常量表达式,用来指定数组的大小,表示有几行几列
【创建实例】
//数组创建
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
【注意】
1、二维数组,放多少行没有所谓,因为默认是往前递增,但是省略列的话,就不知道一行放多少个元素了
2、可以认为二维数组有多少个元素,每个元素就是一个一维数组
3.3 二维数组的使用
二维数组的访问也是通过下标的形式进行的
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;
}
【总结】
二维数组在内存中也是连续存储的
4、数组越界
前提: 数组的下标是有范围限制的。
1、数组的下规定是从0开始的,如果输入有n个元素,最后一个元素的下标就是n-1。
2、数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
3、C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查
【实例分析】
比如数组定义时有十个元素,那么a[0] – a[9] 分别对应相应的元素,在程序中如果使用了a[10]那么就超出了原来的数组定义的范围,这就是数组下标越界。
【注意】
这里编译并没有报错,但是程序确实错的,所以在定义数组的时候,我们要千万小心。二维数组的行和列也可能存在越界。
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;
}
1、前两个值依旧一样,但最后一个跟前两个差了40,因为数组是个元素,一个元素是一个整型,10个就是40个字节
2、最后一个,跳过整个数组,前两个跳过一个元素
3、数组的地址,影响的是整个数组,数组首元素的地址影响的是数组的元素