## 一.数组
+ 用来存放许多相同类型的数据,如一个班有很多的学生。
+ 无论它是一维还是多维,它都占用连续的空间。
## 二.一维数组
#### 1.定义和初始化
**基本格式**
```c
//数组长度必须是一个常量
数据类型 标识符[数组长度] = {初始值,初始值,...};
```
> 这个[数组长度]只是个修饰符,而不是类型的一部分。
**只定义但不初始化**
这时数组中每个元素的初值都是不确定的。如果是静态的,则每个元素的初值为0。
```c
int a[10];
```
**定义并初始化**
```c
//初始化全部元素
int a1[5] = {1,2,3,4,5};
//初始化前3个元素,后面两个元素则被编译器初始化为0.
int a2[5] = {1,2,3};
//下面这句话也是对的,一维的长度可省,编译器会自动判断长度。省掉后数组必须初始化,不然编译器咋知道你要多大的空间。
int a3[] = {1,2,3};
//下面这句话是错的哎
int a4[1] = {1,2,3};
```
#### 2.访问数组
**访问和修改数组元素**
用数组名+下标访问和修改即可。
**注意,编译器不会检查数组越界。**
```c
a1[1] = 100;
```
#### 3.数组名称的含义
+ 它是数组类型,不是指针类型。可以 `sizeof` 数组名试试。
+ **万恶之源** 大多数用到数组名的地方,编译器会自动将其转换为指向数组第一个元素的指针右值。除了用 `sizeof` 运算符、`typeid` 运算符、取地址运算符 `&` 访问数组,或用数组初始化引用。
**不可以对数组整体赋值** 你能对一个右值赋值嘛?
此外,也不可以用一个数组去初始化另一个数组。
> 需要注意的是,数组是 **可复制的** 。但只是数组到指针右值的转换导致不能直接使用 `=` 进行赋值或用另一个数组来初始化。
#### 4.向函数传递一维数组
+ 如果形参是数组,则编译器会自动替换成指针。
+ 所以形参中声不声明一维数组的大小是无所谓的。
```c
void sort(int arr[],int size);
//编译器替换后,arr就是指针
void sort(int *arr,int size);
```
> 注意,这个不是转换,而是直接替换。转换会生成一个新的值,而不改变自身值,而替换,就很简单粗暴了。
```c
int i = 2;
double d = i;//i的值会拷贝一份,转换成double型,但是操作完后i的值仍是int。
```
#### 5.向函数返回一维数组
这是不允许的操作~~
下面这个写法也是错的。
函数返回的时候a已经没了,返回的地址就不知道指向什么地方了。
```c
int* return_a_array()
{
int a[10];
return a;
}
```
## 三.二维数组
#### 1.定义和初始化
**基本格式**
```c
//数组长度必须是一个常量
数据类型 标识符[一维的长度][二维的长度] = 初始化列表;
```
跟上面的一维数组的定义和初始化差不多的,你可以只定义而不初始化,也可以定义的时候初始化。
对于初始化语句,你可以进行分开赋值,也可以进行连续赋值:
```c
//连续赋值
int arr1[2][3] = {1,2,3,4,5,6};//arr1:{{1,2,3},{4,5,6}}
int arr2[2][3] = {1,2};//arr2:{{1,2,0},{0,0,0}}
//分开赋值
int arr3[2][3] = {{1,2,3},{4,5,6}};//arr3:{{1,2,3},{4,5,6}}
int arr4[2][3] = {{1,2},{4,5}};//arr4:{{1,2,0},{4,5,0}}
```
在多维数组的定义和初始化中,只能省掉一维的长度。
```c
//得到 int[2][3]
int arr[][3] = {1,2,3,4,5,6};
```
#### 2.访问数组
**访问和修改数组元素**
用数组名+下标访问和修改即可。
```c
arr[1][1] = 100;
```
#### 3.向函数传递二维数组
+ 如果形参是数组,则编译器会自动替换成指针。
+ 因为这个指针是指向数组的,因此二维部分需要指明大小。
```c
void output(int arr[][20],int size);
//编译器替换后,arr就是指针
void output(int (*arr)[20],int size);
```
#### 3.二维数组各维度的类型
二维数组可以看成 一个每个元素都是数组类型的一维数组。
例如,
```c
int a[5][10];
```
`a` 是一个二维数组,类型为 `int[5][10]`。
`a[0]` 是一个一维数组,类型为 `int[10]`。
`a[0][0]` 则是整型。
## 三.数组与指针的关系
1. 在大多数表达式下,数组名自动转换成指向数组首元素的指针。
2. **[11+]\[$]** 使用数组初始化一个 `auto`关键字定义的变量时,得到一个指向数组首元素的指针。
3. **[11+]\[$]** 获取数组的首尾地址
```c++
//请勿使用VC6.0等古董编译器运行此例
int score[] = {56, 87, 64, 98, 74, 56, 78, 69, 88, 99};
int *start = std::begin(score);//指向第一个元素
int *back = std::end(score);//指向末尾元素的下一个元素
```
- 阅读说明
- 1.1 概述
- C++基础
- 1.2 变量与常量
- 1.2.1 变量
- 1.2.2 字面值常量
- 字符型常量
- 数值型常量
- 1.2.3 cv限定符
- 1.3 作用域
- 1.3.1 标识符
- 1.3.2 *命名空间
- 1.3.3 作用域
- 1.3.4 可见性
- 1.4 数据类型
- 1.4.1 概述
- 1.4.2 处理类型
- 类型别名
- * auto说明符
- * decltype说明符
- 1.4.3 数组
- 1.4.4 指针
- 1.4.5 引用
- 1.5 表达式
- 1.5.1 概述
- 1.5.2 值的类别
- 1.5.3 *初始化
- 1.5.4 运算符
- 算术运算符
- 逻辑和关系运算符
- 赋值运算符
- 递增递减运算符
- 成员访问运算符
- 位运算符
- 其他运算符
- 1.5.5 *常量表达式
- 1.5.6 类型转换
- 第2章 面向过程编程
- 2.1 流程语句
- 2.1.1 条件语句
- 2.1.2 循环语句
- 2.1.3 跳转语句
- 2.1.4 *异常处理
- 2.2 函数
- 2.2.1 概述
- 2.2.2 函数参数
- 2.2.3 内置函数
- 2.2.4 函数重载
- 2.2.5 * 匿名函数
- 2.3 存储和生命期
- 2.3.1 生命周期与存储区域
- 2.3.2 动态内存
- 2.4 *预处理命令
- 第3章 面向对象编程
- 3.1 概述
- 3.2 类和对象
- 3.3 成员
- 3.3.1 访问限制
- 3.3.2 常成员
- 3.3.3 静态成员
- 3.3.4 成员指针
- 3.3.5 this指针
- 3.4 特殊的成员函数
- 3.4.1 概述
- 3.4.2 构造函数
- 3.4.3 析构函数
- 3.4.4 拷贝语义
- 3.4.5 * 移动语义
- 3.5 友元
- 3.6 运算符重载与类型转换
- 3.6.1 概述
- 3.6.2 重载方法
- 3.6.3 类型转换
- 3.7 继承与多态性
- 3.7.1 概述
- 3.7.2 派生类
- 3.7.3 子类型
- 3.7.4 虚基类
- 3.7.5 虚函数
- 3.7.6 抽象类
- 3.8 模板与泛型
- 3.8.1 概述
- 3.8.2 模板类型
- 3.8.3 *模板参数
- 3.8.4 *模板编译
- 3.8.5 *模板推断
- 3.8.6 *实例化与特例化
- 第4章 C++标准库
- 4.1 概述
- 4.2 输入输出流
- 4.2.1 概述
- 4.2.2 *流的状态
- 4.2.3 *常用流
- 4.2.4 *格式化I/O
- 4.2.5 *低级I/O
- 4.2.6 *随机访问
- 4.3 *C输入输出
- 4.3.1 *字符输入输出
- 4.3.2 *格式化输入输出
- 4.4 * 容器
- 4.4.1 * 概述
- 4.4.2 * 基本操作
- 4.4.3 * 顺序容器
- 4.4.4 * 迭代器
- 4.4.5 * 容器适配器
- 4.5 * 泛型算法
- 4.6 * 内存管理
- 4.6.1 * 自动指针
- 4.7 * 其他设施