什么是数组?
数组是一组类型相同元素的容器.数组中存放的对象没有名字,必须通过位置来访问.数组的大小确定不变, 一旦数组定义完成,不能再向数组中添加元素.
数组基本概念
数组是一种复合类型.数组的声明形如a[d], 其中a是数组的名字,d是数组的维度.维度说明了数组中元素的个数,因此必须大于0. 数组中元素的个数也属于数组类型的一部分,编译时数组的维度必须是已知的.
适用所有数组类型
- 不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。
- 在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。当对数组名称使用decltype关键字时得到的是数组对象类型。
- 对数组执行下标运算其实是对指向数组元素的指针执行下标运算
- 内置的下标运算符不是无符号数,标准库类型如vector和string限定使用的下标必须是无符号数
- 因为数组本身是对象,可以定义数组的指针和数组的引用
适用于字符数组
当使用字符串常量对字符数组进行初始化时, 字符串数组最后一位会被加上一个’\0’空字符
但是使用strlen()计算该数组的长度时,该字符串末尾的空字符不计算在内对字符数组进行列表初始化时,字符数组末尾没有空字符; 但是由于strlen()函数时是使用空字符来判断字符串结束的, 无法对这样的字符数组使用strlen()求长度
代码示例
字符数组初始化和求长度
- 字符数组初始化有两种方式,列表初始化和字符串常量初始化
- 字符串常量初始化时,字符串常量末尾的空字符也会拷贝到字符数组中去
1 | void testCharArray() { |
运行结果
1 | strlen("danam"): 5 |
数组名和指针,迭代器
- 数组名通常会自动转换为指向数组首元素的指针
- 在表达式decltype(arr)时,不会发生自动转换,decltype(arr)的返回类型是一个数组类型,其元素类型和维度都与数组arr相同
1 | void testCharArray1() { |
运行结果
1 | nice to meet you alice |
指针运算
- 对数组执行下标运算其实是对指向数组元素的指针执行下标运算。标准库类型使用的下标类型必须是无符号类型,内置的下标运算可以是带符号类型
- 可以从一个指针加上或减去一个整数值,结果仍是指针
- 指向同一个数组中元素(包括尾元素)的指针可以相减,两个指针相减的结果是一种名为ptrdiff_t的标准库类型。ptrdiff_t类型是一种带符号类型
1 | void testCharArray3() { |
运行结果
1 | s1: you |
指针和迭代器
1 | void testCharArray2() { |
运行结果:
1 | 0 1 2 3 4 5 6 7 8 9 |
牛客网遇到的一些题
若有以下说明和语句,int c[4][5],(*p)[5];p=c;能正确引用c数组元素的是( )。
A. p+1 B.*(p+3) C.*(p+1)+3 D.*(p[0]+2)
解答:
int (p)[n]; 因为()的优先级更高,所以p是一个指针,指向一个整形的一维数组,这个一维数组的长度是n,n也可以说是p的步长。也就是说执行p+1时,p要跨过n个整形数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int c[4][5]; int (\p)[5]; // 定义一个数组指针,指向含5个元素的一维数组
p = c; // 将二维数组c的首地址赋给p,也就是p = c[0] 或者 p = &c[0][0]
(p[0] + 2); // 等价于\(*(p+0) + 2),表示a[0][2]