
第二课:邮递员坐上小火车------一维数组与指针
🎯本章学习目标
学完本章,同学们能够:
✅ 理解为什么指针可以指向数组
✅ 理解 int *p = train;
✅ 掌握 *p
✅ 掌握 p+1
✅ 掌握 *(p+i)
✅ 理解
a[i]
为什么等于
*(a+i)
并能够举一反三。
第一章 邮递员的新工作
1、上一章,我们认识了小火车。
int train[5]={10,20,30,40,50};
2、它在内存里是这样排列的:
地址:
1000 1004 1008 1012 1016
┌────┬────┬────┬────┬────┐
│10 │20 │30 │40 │50 │
└────┴────┴────┴────┴────┘
3、汉克老师问大家:
如果国王想知道:
第四节车厢里装了什么。
怎么办?
4、以前的方法:
cout<<train[3];
是不是可以?
当然可以!
5、但是今天。
国王想派:
📮 邮递员小P。
让他负责整列火车。
第二章 邮递员正式上车
1、汉克老师写下一句代码。
int *p = train;
(1)有的同学第一次看到都会问:
汉克老师!
为什么没有写:
&p
(2)为什么:
train
就可以?
2、汉克老师笑着说:
(1)上一章已经告诉大家了。
train
在这里表示:
&train[0]
也就是:
第一节车厢地址。
(2)所以:
其实这一句真正的意思是:
int *p = &train[0];
是不是一下就熟悉了?
(3)因为以前我们写过:
int age = 10;
int *p = &age;
(4)只是现在。
变量变成了:
train[0]
而已。
第三章 邮递员拿到了什么?
1、汉克老师问:
执行:
int *p = train;
以后。
p里面到底装着什么?
2、很多同学说:
装着:
10
错!
3、还有同学说:
装着:
整个数组
也错!
4、真正装着的是:
第一节车厢地址
(1)假设是:
1000
(2)于是:
内存可以画成:
p
│
│1000
▼
1000 1004 1008 1012 1016
┌────┬────┬────┬────┬────┐
│10 │20 │30 │40 │50 │
└────┴────┴────┴────┴────┘
(3)汉克老师笑着说:
p 永远保存地址,不保存数据。
这一点和以前学习普通变量指针时,一模一样。
第四章 第一个实验------*p 到底是什么?
1、汉克老师问:
现在:
int *p=train;
那么:
*p
是多少?
2、我们一步一步分析。
(1)第一步。
看:
p
里面是什么?
答案:
1000
(2)第二步。
去:
1000号车厢。
(3)第三步。
打开车厢。
里面放着:
10
(4)所以:
*p
就是:
10
3、来看程序。
#include<iostream>
using namespace std;
int main()
{
int train[5]={10,20,30,40,50};
int *p=train;
cout<<*p<<endl;
}
输出:
10
4、是不是和我们以前学习的指针一模一样?
一点都没有变!
(1)只是以前:
p
指向一个变量。
(2)现在:
p
指向数组里的第一个元素。
第五章 邮递员向前走一步
1、汉克老师继续问:
(1)如果想去第二节车厢。
怎么办?
(2)很多同学说:
再定义一个指针。
(3)其实不用。
邮递员会走路。
2、汉克老师写:
p+1
(1)汉克老师没有急着讲代码。
而是讲了一个故事。
(2)邮递员站在:
第一节车厢。
🚂🚃🚃🚃🚃
↑
p
现在。
国王说:
向前走一步。
(2)于是:
🚂🚃🚃🚃🚃
↑
p+1
是不是到了:
第二节?
(3)再走一步。
🚂🚃🚃🚃🚃
↑
p+2
到了:
第三节。
(4)所以:
以后看到:
p+i
同学们脑子里一定要想到:
邮递员向后走 i 节车厢。
千万不要去死记公式。
第六章 p+1 为什么不是1001?
1、有的同学会问:
汉克老师。
地址不是:
1000
吗?
为什么:
p+1
不是:
1001
2、这是一个经典问题!
(1)汉克老师重新画图。
1000 1004 1008 1012
┌────┬────┬────┬────┐
│10 │20 │30 │40 │
└────┴────┴────┴────┘
(2)汉克老师说:
注意!
每节车厢不是占一个房间。
而是:
占四个房间。
(3)因为:
int
占:
4个字节。
(4)所以:
邮递员说:
向后一节。
其实就是:
跳过四个字节。
(5)于是:
1000
↓
1004
这就是:
p+1
3、汉克老师强调一句:
p+1不是地址加1,而是移动到下一个int元素。
计算机会自动根据数据类型计算步长。
第七章 * (p+1)
1、汉克老师继续。
如果:
p+1
到了第二节。
2、那么:
*(p+1)
是什么意思?
3、大家已经猜到了
没错!
(1)第一步:
p+1
来到第二节。
(2)第二步:
*
打开车厢。
(3)于是:
得到:
20
4、程序:
#include<iostream>
using namespace std;
int main()
{
int train[5]={10,20,30,40,50};
int *p=train;
cout<<*(p+1)<<endl;
}
输出:
20
5、再来看。
*(p+2)
(1)先走两步。
来到:
第三节。
(2)打开。
得到:
30
6、汉克老师总结:
先移动,再打开。
这就是:
*(p+i)
第八章 神奇的秘密
1、汉克老师写下两句代码。
train[3]
和:
*(train+3)
2、汉克老师问:
它们一样吗?
答案:
完全一样!
3、为什么?
我们分析。
(1)第一步。
train
表示:
索引为0节的地址。
(2)第二步。
train+3
向后走三节。
来到:
索引为3节的地址。
(3)第三步。
*
打开索引为3节的地址。
(4)得到:
40
所以:
*(train+3)
就是:
40
(4)而:
train[3]
本来就是:
索引为3。
所以:
它们完全一样。
第九章 对照表
1、一张对照表。
| 数组写法 | 指针写法 | 得到的值 |
|---|---|---|
train[0] |
*train |
10 |
train[1] |
*(train+1) |
20 |
train[2] |
*(train+2) |
30 |
train[3] |
*(train+3) |
40 |
train[4] |
*(train+4) |
50 |
2、汉克老师笑着说:
(1)以后看到:
a[i]
(2)脑子里马上想到:
*(a+i)
(3)看到:
*(a+i)
马上想到:
a[i]
两种写法是可以互相转换。
第十章 一个完整实例
#include <iostream>
using namespace std;
int main()
{
int train[5]={10,20,30,40,50};
cout<<train[0]<<endl;
cout<<*(train+0)<<endl;
cout<<train[2]<<endl;
cout<<*(train+2)<<endl;
cout<<train[4]<<endl;
cout<<*(train+4)<<endl;
return 0;
}
输出:
10
10
30
30
50
50
这说明:
无论使用数组下标,还是指针运算,访问到的都是同一个元素。
第十一章 常见错误
❌ 错误一:认为 p 保存的是整个数组
错误理解:
p
↓
整个数组
正确理解:
p
↓
第一节车厢地址
❌ 错误二:认为 p+1 是地址加1
错误:
1000
↓
1001
正确:
1000
↓
1004
因为 int 一般占4个字节。
❌ 错误三:忘记解引用
例如:
cout<<p+2;
输出的是:
地址。
如果想得到第三节车厢里的数据。
应该写:
cout<<*(p+2);
🌟 本章总结
今天,我们学会了让邮递员在小火车上自由行走。
记住下面几句话:
-
train在很多情况下表示第一节车厢(首元素)的地址。 -
int *p = train;表示让指针p指向数组的第一个元素。 -
*p表示第一节车厢里的数据。 -
p+1表示走到下一节车厢。 -
*(p+1)表示打开第二节车厢,取出里面的数据。 -
train[i]和*(train+i)是两种不同的写法,但表示的是同一个元素。
🌈 本章口诀
火车车头地址来,
邮递员把它装怀。
星号打开第一节,
加一走向下一排(下一节)。
先移动来后开门,
数据自然眼前来。
数组下标和指针,
两种写法一样帅!
🚀 下一章预告
下一章,我们将进入本课有挑战性的内容:
《两层小火车站------二维数组与指针》
这一次,火车不再只有一排,而是变成了两层车站。