文章目录
一维数组
一维数组的创建
什么是数组?
数组是一组相同类型元素的集合。
数组的创建方式:
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_t 是一个常量表达式,用来指定数组的大小。
数组创建实例:
代码1:
int arr1[10];
代码2:
int a=10;
int arr2[a];
//注意:创建数组时,数组的常量表达式不能是变量
//这里 a 虽然被赋值,但是它的 本质 还是一个 变量
//所以,这里是一个 错误示范,这样创建数组的时候,是不会被语法允许的
代码3:
#define count 100
int main()
{
int arr3[count];
}
//这里的 count 是全局变量
//虽然它也是叫做变量
//但是它在被代码块引用的时候,通常被当作常量来引用。
代码4:
int arr4[]={1,2,3,4};
//数组在创建的时候如果想不指定数组的确定的大小就得初始化。
//数组的元素个数根据初始化的内容来确定。
//一定不能这样创建:
int arr4[];
//这样创建编译器会报错
//因为它不知道该分配给 arr4[] 数组多少空间
代码5:
char arr5[10];
float arr6[10];
double arr7[10];
一维数组的初始化:
数组的初始化是指,在创建数组的同时给数组的内容一些合理的初始值(初始化)。
int arr1[10]={1,2,3,4,5,6,7,8,9,10};
int arr2[10]={1,2,3,4};
char arr3[5]={'a','98','c'};
char arr4[]={'a','b','c'};
char arr5[]="abc";
这里有个值得小小注意的地方,就是arr4和arr5这两个数组的大小
arr4是字符串,arr5是字符。
字符数组在你创建的时候没有规定大小,而是由初始化来规定大小的时候,你初始化的大小是多少,就是多少
字符串数组在你创建的时候没有规定大小,而是由初始化来规定大小的时候,你初始化的大小是多少,就在你初始化的大小上+1,因为在字符串里面是默认最后面跟上了一个 '\0'
一维数组的使用
对于数组的使用,我们之前介绍了一个操作符:[]——下标引用操作符。
它其实就是数组的访问操作符。
#include <stdio.h>
int main()
{
int arr[10] = {0};
//数组的不完全初始化
//计算数组的元素个数
int sz = sizeof(arr)/sizeof(arr[0]);
//对数组内容赋值
//数组是使用下标来访问的,下标从0开始。
//所以:
int i = 0;
//做下标
for(i=0; i<sz; i++)
//这里的条件判断在知道数组大小的时候
//可以直接用数组大小也可以用sz
//但是不知道数组大小的时候,你只能用sz
{
arr[i] = i;
}
//输出数组的内容
for(i=0; i<10; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}
总结:
1.数组是使用下标来访问的,下标是从0开始。
2.数组的大小是可以通过计算得到的
计算数组大小的用操作符sizeof计算
sizeof(数组名)计算的是数组的大小,
sizeof(数组名[0])计算的是数组单个元素的大小
int arr[10];
int sz = sizeof(arr)/sizeof(arr[0]);
一维数组在内存中的存储
数组在内存中的存储,是连续存放的,并且数组中元素的地址也是随着数组下标的增长而增长
下面让我们来直观感受下:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; ++i)
{
printf("&arr[%d]=%p\n",i, &arr[i]);
}
return 0;
}
代码输出结果:
注:在内存中,地址一般是用十六进制表示
因为一个int型的数据大小是4个字节,所以这里int型的数组,每个元素的之间的地址相差4
二维数组
二维数组的创建
什么是二维数组?
二维数组实际上是一种平面的二维结构,本质上是数组的数组。
创建实例:
int arr[2][3]={{1,2,3},{4,5,6}};
二维数组的初始化
二维数组的大多数注意事项同一维数组的注意事项一样
下面介绍不同于一维数组的地方
不同的:
int arr[][3]={1,2,3,4,5,6};
//二位数组在创建的时候行可以省略,但是列不能省
//省略了行可以在初始化的时候根据列的数量来进行分行
//但是如果省略了列,那就没有办法进行分行的操作
int arr1[3][4]={{1,2},{3,4,5},{9,8,7,6}}
//在限定了二位数组的大小的前提下,二维数组每一行的元素可以不用写满,会自动补0
int arr2[2][3]={1,2,3,4,5};
//在没有{}将数组的数据分好的情况下,数组会自动默认排序
//在第一行排完之后排第二行,如果数据不够,自动补0
//
//对于二维数组的字符串输入、输出,代码如下:
#include<stdio.h>
int main()
{
//存储3个字符串,每个不超10
char arr[3][10] = { 0 };
//输入数据(字符串)
for (int i = 0; i < 3; i++)
{
printf("请输入字符串:\n");
scanf("%s", arr[i]);
//每一行输入数据,故而只需要显示行的常量
//但是要注意,输入的数据不能超过列的限制,不然就会造成数据溢出
}
//打印数据
for (int j = 0; j < 3; j++)
{
printf("打印数据为:%s\n", arr[j]);
}
return 0;
}
二维数组的使用
#include<stdio.h>
int main()//打印一个九宫格的*
{
char arr[3][3];
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
arr[i][j] = '*';
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("%c ",arr[i][j]);
}
printf("\n");
}
return 0;
}
效果图:
二维数组在内存中的存储
二位数组和一维数组的存储方式一样,是连续存放的,并且数组中元素的地址也是随着数组下标的增长而增长
让我们感受一下:
#include<stdio.h>
int main()
{
int arr[2][3];
int i = 0, j = 0;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 3; j++)
{
printf("&arr[%d][%d]=%p\n",i,j,&arr[i][j]);
}
}
return 0;
}
数组越界
讨论完了数组创建,初始化,使用和存储之后,就要来讲解到一个非常重要的知识点——数组越界
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果输入有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错
但是编译器不报错,并不意味着程序就是正确的
所以程序员写代码时,最好自己做越界的检查。
例如:
#include<stdio.h>
int main()
{
int i = 0;
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
for (i = 0; i <= 12; i++)
{
arr[i] = 0;
printf("%d",arr[i]);
}
return 0;
}
这里的代码访问就越界了,但是作者用的VS2019并没有报错,但是它却死循环了,死循环的原因是为什么呢?
局部变量的存储是存放在栈区的
栈的使用规则是先进后出,即先用高地址,再用低地址,调用栈的时候,是先低地址出去,然后高地址出去
元素的地址是:随着下标的增长由低到高变化的
编译器的差异会导致缓冲区的大小不同
例如:
vc6.0中 arr和i 是连着的,没有缓冲区
vs2013–vs2019(除了vs2017),缓冲区有两个空间
gcc中则只有一个
所以说千万别忽视了数组越界,这个示例还是曾经的一道经典面试题!
数组作为函数参数
在数组作为函数参数时,通常是作为首元素地址
结论
数组名除了两种情况以外,都是作为首元素地址
- 1.sizeof(数组名),计算的是整个数组的大小,此时的数组名代表 的是整个数组
- 2.&数组名,取出的是整个数组的地址,此时的数组名代表的是整个数组
例如(冒泡排序):
#include<stdio.h>
void Sort(int* arr, int sz)
{
int i = 0;
int j = 0;
for (i = 0; i < sz - 1; i++)//数组不需要和自己比较
{
for (j = 0; j < sz - i - 1; j++)//没排好一个数,就要少排一个
{
if (arr[j] > arr[j + 1])//将大的数置换到后面去
{
int tmp = arr[j];创建一个空的临时变量来中转
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = {9,8,7,6,5,4,3,2,1,0};
int sz = sizeof(arr) / sizeof(arr[0]);//这里计算的是数组元素的个数
Sort(arr, sz);//这里的数组名作为函数参数时,是代表数组首元素地址
for (int i = 0; i < 10; i++)
{
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
效果图: