【fishing-pan:https://blog.csdn.net/u013921430转载请注明出处】
前言 数组是C/C++以及各种编程语言中最常用的一种数据结构,了解数组的性质并且学会使用数组是对于程序员最基本的要求。今天给大家介绍一下数组,介绍主要分为静态数组与动态数组两部分。
注:这里讲到的静态数组不是使用static 关键字修饰的数组,而是普通的数组,为了与后面的动态数组分离开,才说明它是静态数组。
静态数组 数组是一种复合的类型,因此在定义数组时必须显式指定数组的类型,不能使用auto关键字,静态数组的声明形如a[d];
a是数组的名字,d是数组的维度。维度说明了数组中元素的个数,因此d必须大于0。
在进行编译时,d必须是已知的,即编译器在编译时d已经是可以确定的值,因此数组的维度必须是一个常量表达式。
补充:常量表达式是指不会改变且在编译过程就能得到计算结果的表达式,显然字面值属于常量表达式。
静态数组的初始化
int S = 10;
int arr[S];
//错误,S不是常量表达式 int *prr[10];
//正确,10是常量表达式 const int M = 10;
int A[M] = { 10 };
//正确,M是常量表达式
string C = "fishing_pan";
const int N = C.length();
char B[N];
//错误,N不是常量表达式,因为N在运行时候才被初始化
在上面的数组中可以看到,数组的维度必须是常量表达式。
在定义的时候可以对静态数组进行列表初始化,而进行列表初始化时,可以不声明数组的维度,如果没有声明数组的维度,那么编译器会根据初始值推测数组的大小。如果声明了维度,那么数组的初始值的数量不能超过维度,如下面的例子所示。
int arr1[4] = {0, 1, 2 };
//数组大小为4,值分别是0,1,2,0,未列出的值进行默认初始化;char arr2[] = {'P', 'A', 'N' };
//未声明大小,大小为3double arr3[4] ={0,1,2,3,4}//错误,初始值过多
字符数组的特殊性
在字符数组的定义中,可以使用字符串字面值进行定义,这个时候要注意了,字符串默认在结尾处还有一个空字符,空字符需要占用一个位置。
【【C++】细说C++中的数组之“静态”数组】从下面的例子可以看出,初始化字符数组时,可以不标明大小,这样不会出错。
char arr4[3] ="pan";
//错误,"pan"是const char[4]类型,不能用于初始化char arr4[3]char arr5[] ="pan";
//正确,arr5大小为4;
不允许拷贝和赋值
不能将数组内容拷贝给其他数组进行初始化,也不能用数组为其他数组赋值。
数组元素访问 数组元素可以用下标进行访问,也可以实现指针进行访问,需要注意的是,数组的第一个元素的编号是0,而不是1;一个100大小的数组,索引编号是0-99。
char arr5[] = "pan";
char c=arr[2];
//c=’n’;
数组与指针
在C++中,数组与指针的关系非常紧密。指针一般使用取地址符来指向某一对象。同样也可以用于指向一个数组,不同的是,指针不会指向整个数组,而是指向数组中的某个位置;例如
int arr1[4] = { 0, 1, 2 };
int *p = &arr1[1];
//指向arr1的第二个数;
直接将数组的名字传给指针时,默认指向数组的第一个值。
int arr1[4] = { 0, 1, 2 };
int *p = arr1;
//等价于p=&arr1[],指向arr1的第1个数;
指针迭代与迭代器
当遍历数值的值时,可以使用指针进行迭代,只需移动指针即可;
int arr1[4] = { 0, 1, 2 };
int *p = &arr1[1];
++p;
//此时p指向arr1[2];
使用指针遍历虽然简单,但是容易出现超出范围的内存错误。因此可以使用迭代器;
int *beg = begin(arr1);
//指向数组首元素 int *ends = end(arr1);
//指向数组末尾元素的下一位while(beg!=ends)//进行遍历。{cout<< *beg<
多维静态数组 在有些时候,为了使用方便或者观察方便,会定义多维数组,比如读取一张图像,可以用一张二维数组存储图像中对应坐标的灰度值。
多维数组其实就是元素是数组的数组,拿一个二维数组为例,第一个维度表示的是数组的大小,也就说是数组本身有多少个元素。第二个维度表示其元素的大小。
inttwodArr1[4][5];
//定义一个本身大小为4,元素大小为5的数组,共可存储20个整型数据
对于二维数组来说,我们常常把第一个维度称为行,第二个维度称为列,上式定义了一个4行5列的数组。
多维静态数组的初始化
除了一维数组中提到的注意事项外,多维数组进行初始化时,也有一个需要注意的问题。
为了方便理解,可以使用花括号将每一行括起来。
int twodArr2[4][5] = { { 0, 1, 2, 3, 4 }, {5, 6, 7, 8, 9 }, { 0, 1, 2, 3, 4 }, { 5, 6, 7, 8, 9 } };
也可以不适用花括号,由编译器自己判断;
int twodArr3[2][5]= { 0, 1, 2, 3, 4, 5, 6 };
//等价于int twodArr2[2][5] = { {0, 1, 2, 3, 4},{ 5, 6 ,0,0,0}};
注意:定义多维数组时,如果不对它进行初始化,必须标明每个维度的大小;如果进行了显式的初始化,可以不标明最高维度的大小,(也就是第一个维度,当第一个维度不标明大小,则不需进行初始化);
inttwodarr4[][][5] = { 0, 1, 2, 3, 4, 5, 6 };
//错误,需标明第二个维度的大小inttwodarr5[][5] = { 0, 1, 2, 3, 4, 5, 6 };
//正确;inttwodarr5[][5];
//错误,必须声明每一个维度的大小
多维数组与指针及迭代器
int twodarr[3][4];
int(*p3)[5]= twodArr2;
//指向twodArr2的第一行p3= &twodArr2[1];
//指向twodArr2的第二行cout << *(*p3) << endl;
//输出为5,第二行第一个数字
可以看出,我们使用指针对数组进行迭代,当然,也可以使用迭代器;
for (auto p = begin(twodArr2);
p !=end(twodArr2);
p++){for(auto q = begin(*p);
q != end(*p);
q++){cout<< *q << " ";
}cout<< endl;
}
文章图片
至此,静态数组讲解的差不多了,如果大家有不理解的地方,可以把上面的代码都自己写一下,就能够明白为什么。后面,会写一篇动态数组的博文。并且讲一下静态数组与动态数组的区别。 未完.......
相关文章细说C++中的数组之动态数组
推荐阅读
- 个人日记|K8s中Pod生命周期和重启策略
- 学习分享|【C语言函数基础】
- C++|C++浇水装置问题
- 数据结构|C++技巧(用class类实现链表)
- C++|从零开始学C++之基本知识
- 步履拾级杂记|VS2019的各种使用问题及解决方法
- leetcode题解|leetcode#106. 从中序与后序遍历序列构造二叉树
- 动态规划|暴力递归经典问题
- 麦克算法|4指针与队列
- 遇见蓝桥遇见你|小唐开始刷蓝桥(一)2020年第十一届C/C++ B组第二场蓝桥杯省赛真题