声明一个一维数组就一句话:类型 数组名[长度];。长度必须是编译期能确定的常量,声明完格子就分配好了,但里面是垃圾值(跟 2.3.2 的"未初始化"一模一样,只是从 1 格变成了一排)。
7.1 讲了"数组是什么、为什么要有"。这一节落地"怎么把一排柜子订出来"。写声明的零件都是旧朋友:类型来自第二章、数组名要守 2.3.1 的标识符规则、长度必须是常量、分号别忘了(1.3.2 的铁律)。下一节 7.1.2 解决"柜子订好了,怎么打开某一格"。
一、声明的格式
类型 数组名[长度];
三样东西各有讲究:
| 部分 | 写法 | 说明 |
|---|---|---|
| 类型 | int / double / char |
每个格子的规格,全数组统一 |
| 数组名 | score |
守标识符规则(2.3.1);别和变量重名 |
| 长度 | [50] |
格子的数量,写在方括号里(不是圆括号!) |
几个合法的例子:
int score[50]; // 50 个整数格
double price[100]; // 100 个小数格
char name[20]; // 20 个字符格(7.3 的字符数组)
读完要能自动翻译成大白话:int score[50]; = "给我订一排 50 格的整数柜,整排叫 score"。
二、长度的三条硬规矩
规矩 1:长度必须是"常量表达式"
int a[5]; // ✅ 字面量常量
const int N = 5;
int b[N]; // ✅ const 常量(2.2.5 的 const,编译期已知)
#define M 5
int c[M]; // ✅ 宏常量
int n = 5;
int d[n]; // ❌ 标准 C++ 不允许:n 是"变量",值要到运行时才知道
为什么这么严?因为在 7.1 的内存图里,数组是一整块连续空间。编译器在生成代码时就得把这块空间的尺寸定死,才能算出后面的变量该放在哪。如果长度能随便变,整个内存布局就没法安排了。
小提示:Dev-C++ 里
int d[n];有时居然能编过(g++ 的"变长数组"扩展),但这是非标准行为,换个编译器就报错。别依赖它。
规矩 2:长度是"格数",不是"最大下标"
int a[5]; // 5 格: a[0] a[1] a[2] a[3] a[4]
[5] 是格子数量。合法下标是 0~4,没有 a[5]。写 [5] 然后去用 a[5],是新手最常犯的错(7.1.2 详述"越界")。
规矩 3:声明 ≠ 摆放
int score[5]; // 只订了柜子,格子是空的(垃圾值)
语句执行完,格子里是什么完全不确定。有的编译器(Debug 模式)会顺手刷成 0,有的直接留着垃圾值。"在我这儿是 0"是最危险的错觉——换台机器、换个模式就变了。想让它干净,看 7.1.3 的初始化。
三、声明完能立刻问的三个问题
int a[5];
sizeof(a) // 20:整排占多少字节
sizeof(a[0]) // 4 :一格占多少字节
sizeof(a) / sizeof(a[0]) // 5 :一共几格(不写死数字的标准写法)
最后一行是本节最实用的技巧。以后数组长度可能改(从 5 改成 50),遍历时写 i < sizeof(a)/sizeof(a[0]) 就不用跟着改数字,改一处全生效——这正是 6.1 说的"函数/常量的价值:改一处、全生效"。
四、动手 Demo:量一量自己订的柜子
#include <iostream>
using namespace std;
int main() {
int score[5];
double price[4];
char name[13];
cout << "score 整排字节 = " << sizeof(score) << endl;
cout << "score 一格字节 = " << sizeof(score[0]) << endl;
cout << "score 一共格数 = " << sizeof(score) / sizeof(score[0]) << endl;
cout << "price 一共格数 = " << sizeof(price) / sizeof(price[0]) << endl;
cout << "name 一共格数 = " << sizeof(name) / sizeof(name[0]) << endl;
return 0;
}
看到什么算成功:依次输出 20、4、5、4、13。
读结果:int 一格 4 字节(2.3.3),排 5 格就是 20;double 一格 8 字节,排 4 格就是 32 字节(所以格数是 32/8 = 4,不是 4 字节);char 一格 1 字节,13 格就是 13 字节。
30 秒实验:把 int score[5]; 改成 int score[50];,重新运行——每一个数字自动变成 10 倍,输出 200、4、50。全程只改了一处。
五、常见误区
- "方括号里写的是最大下标"——写的是格子数量。
int a[5]的合法下标是0~4。记住口诀:写数量、用数量减一。 - "
int n = 5; int a[n];我这儿能编过啊"——那是 g++ 的扩展,不是标准 C++。换成 MSVC 或加编译参数就报错。const才是正路。 - "声明完格子里是 0"——不保证。未初始化=垃圾值(2.3.2 的老朋友),只是现在垃圾有 5 份。要干净就用 7.1.3 的初始化。
- "数组名可以随便换"——数组名不是普通变量。它代表"整排柜子的首地址",不能
a = b;整体赋值,也不能a++;。7.5.1 会讲清这条的来由。
自测三问(点开对答案)
1. `int a[10];` 一共几格?合法下标范围?——10 格;`0~9`。 2. 为什么长度必须是常量?——数组是一整块连续空间,编译器必须在编译期定死尺寸才能安排内存布局。 3. `sizeof(a) / sizeof(a[0])` 有什么用?——不写死数字地数出数组格数,将来改长度不用改循环。- ☐ 7.1.2 一维数组的引用(下一节)
相关笔记
- 一维数组 —— 数组是什么、为什么要有
- 变量的声明及赋值 —— 未初始化=垃圾值的出处
- 其他常量 —— 长度为什么能用
const - sizeof运算符 —— 量数组的尺子
- 🔷 C++基础 · 索引 —— 全课路线图