当前位置:网站首页>数组(一)
数组(一)
2022-08-10 01:33:00 【我可是ikun啊】
目录
本章开始将开始介绍数组,目前只介绍初阶的数组,等到进阶还会介绍到进阶的数组。
本章会介绍到数组的创建、使用、传递以及越界问题。
1. 一维数组的创建和初始化
(1)一维数组的创建:
什么是数组?
数组指的是:一组同种类型元素的集合。数组的创建方式如下:
type_t arr_name [const_n];//type_t 是指数组的元素类型//const_n 是一个常量表达式,用来指定数组的大小
int arr1[10];//这是未初始化的数组,只定义了数组大小
例2:
int count = 10;
int arr2[count];
如果我们将一个变量放在 [ ] 内部哪怕是将变量赋了值,此时并不能创建成功。 原因:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数 组的概念,数组的大小可以使用变量指定,但是数组不能初始化。
(2)数组的初始化:
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
例如:
int arr1[10] = {1,2,3};
int arr2[] = {1,2,3,4};
int arr3[5] = {1,2,3,4,5};
char arr4[3] = {'a',98, 'c'};
char arr5[] = {'a','b','c'};
char arr6[] = "abcdef";
但是在对于字符类型的初始化要注意一下。
char ch1[]="abc";
char ch2[3]={'a','b','c'};
可以试着求一下它们的长度;
可以清楚的看见 “ ” 的字符串还包括了\0,所以在sizeof计算字符串长度的时候,还需要特别注意不能漏了\0的存在。
(3)一维数组的使用
对于数组的使用我们之前介绍了一个操作符: [] ,下标引用操作符。它其实就数组访问的操作符。
例如:
#include <stdio.h>
int main()
{
int arr[10] = {0};//数组的不完全初始化
//计算数组的元素个数
int sz = sizeof(arr)/sizeof(arr[0]);
//对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:
int i = 0;//做下标
for(i=0; i<10; i++)//这里写10,好不好?
{
arr[i] = i;
}
//输出数组的内容
for(i=0; i<10; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}
很显然,结果是一定会错的,我们设置的arr数组大小只有10,而我们在for循环赋值时,赋值了11次,那么会造成什么结果呢?指针越界 。 留着等会说。
(4)一维数组在内存中的存储
我们知道数组是由一组相同类型的元素所组成,所以它们所在的地址也是连续存在的。
我们试着证明一下:
#include <stdio.h>
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]);
}
return 0;
}
上图的结果是以16进制打印的,c表示12,所以arr[0]和arr[1]之刚好差了4,而他们的单位是字节,int又是以4个字节为单位的。所以得出结论:数组在内存中的存储时是连续的。
二:二维数组的创建和初始化
(1)二维数组的创建
二维数组是建立在一维上的,类似一个矩阵
int arr[3][4];
char arr[3][5];
double arr[2][4];
(2)二维数组的初始化
int arr[3][4] = { {1,2},{4,5}};//不完全初始化
int arr[][4] = { {2,3},{4,5}};//二维数组如果有初始化,行可以省略,列不能省略
(3)二维数组的使用
二维数组也是用 [ ]来访问数组元素。
#include <stdio.h>
int main()
{
int arr[3][4] = {0};
int i = 0;
for(i=0; i<3; i++)
{
int j = 0;
for(j=0; j<4; j++)
{
arr[i][j] = i*4+j;
}
}
for(i=0; i<3; i++)
{
int j = 0;
for(j=0; j<4; j++)
{
printf("%d ", arr[i][j]);
}
}
return 0;
}
(4)二维数组在内存中的存储
例:
结论:二维数组在内存中的存储也是连续的。
三:指针越界:
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就
是正确的,
所以程序员写代码时,最好自己做越界的检查
回到上面所提到的问题,我们在打印最后一个arr[10]时会出现随机值,因为arr[10]并不在我们所定义的范围内。
而对于二维数组而言,二维数组的行和列也可能存在越界。
四:数组传参
往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序(这里要讲算法思想)函数将一个整形数组排序。
例如:
#include <stdio.h>
void bubble_sort(int arr[])
{
int sz = sizeof(arr) / sizeof(arr[0]);//这样对吗?
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
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[] = { 3,1,7,5,8,9,0,2,4,6 };
bubble_sort(arr);//是否可以正常排序?
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
能否正常排序呢?答案是否定的,原因在于,我们并不能直接传递整个数组,所以在int sz = sizeof(arr) / sizeof(arr[0]);这一步算出的结果为1。因为在c语言设计为了防止浪费空间,而创建了传地址,如果一个数组arr[1000000]或则更大,而我们不一定全部用上,那么势必会造成空间的浪费。我们知道数组的地址是连续的,所以我们只需要传递首元素的地址,我们就可以找到余下的所有的元素,很好的节省了空间。
那么我们怎么改进呢?
(1)数组名是什么?
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%d\n", *arr);
//输出结果
return 0;
}
可以清楚的看到arr数组名就是首元素的地址。
一般的数组名就是首元素的地址,但是存在两个意外:
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数
组。
2. &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
(2)正确的设计:
既然无法在函数中求出数组大小,我们可以在mian中去求数组长度,在将长度传进bubble_sort函数中。
void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
//代码同上面函数
}
int main()
{
int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);//是否可以正常排序?
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
结束语:
当然数组的内容远不止这些,我们在c语言进阶的内还会再次见到数组。
边栏推荐
猜你喜欢
Sikuli's Automated Testing Technology Based on Pattern Recognition
不是吧,连公司里的卷王写代码都复制粘贴,这合理?
[LeetCode] Find the sum of the numbers from the root node to the leaf node
Initial attempt at UI traversal
Janus actual production case
3dmax如何制作模型走路动画
OpenCV图像处理学习四,像素的读写操作和图像反差函数操作
Unity image is blurry after using long image
Open3D 泊松盘网格采样
【论文粗读】(NeurIPS 2020) SwAV:对比聚类结果的无监督视觉特征学习
随机推荐
Screen 拆分屏幕
Unity开发者必备的编辑器技巧
grafana9配置邮箱告警
【SSRF漏洞】实战演示 超详细讲解
Janus actual production case
openpose脚部标注问题梳理
odoo公用变量或数组的使用
Experimental support for decorators may change in future releases.Set the "experimentalDecorators" option in "tsconfig" or "jsconfig" to remove this warning
中级xss绕过【xss Game】
《GB39732-2020》PDF download
OpenSSF的开源软件风险评估工具:Scorecards
2022年8月1日-8月7日(本周10小时,合计1422小时,剩余8578小时)
gbase 8a数据库如何查看数据或数据文件是否正常?
C# 正则表达式分组查询
不是吧,连公司里的卷王写代码都复制粘贴,这合理?
【UNR #6 C】稳健型选手(分治)(主席树)(二分)
你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06
unity 报错 Unsafe code may only appear if compiling with /unsafe. Enable “Allow ‘unsafe‘ code“ in Pla
【每日一题】1413. 逐步求和得到正数的最小值
[QNX Hypervisor 2.2用户手册]10.14 smmu