1.指针
例题来源于fishc论坛,侵删。
指针作为c++中最为关键的一部分,是我们学习的一大难点。指针是c语言的”皇冠“。可以这么说,理解了指针,就已经基本对c语言有了全新的认识。
内存
0.冯-诺依曼结构
1964年,第一台计算机ENIAC诞生,人类进入计算机时代,后来,美籍匈牙利数学家:冯.诺依曼提出了计算机“存储程序”的计算机设计理念,即将计算机指令进行编码后存储在计算机的存储器中,需要的时候可以顺序地执行程序代码,从而控制计算机运行,这就是冯.诺依曼计算机体系的开端。
冯.诺依曼确定了”计算机结构“中的5大部件:
- 运算器
- 控制器
- 存储器
- 输入设备
- 输出设备
1.从组装计算机来理解内存
计算机部件主要分为这么几块:
- 主板 (搭载所有组件的地基)
- CPU (运算核心) (缓存)5000m / s
- 内存 (运算的存储核心) 100m / s
- 显卡
- 硬盘 (存储) 0.5m/s
- 电源
- 外接设备
其中,计算机最小的组成部件就是1、2、3、6
内存条的图片:
2.内存和指针是什么关系?
内存其实就是存储数据的地方,他的特性是速度快,但是不通电就会丢失。
在程序运行时,提供数据给CPU运算,并且根据CPU的指令保存数据。
我们都知道,电脑都是以二进制进行存储的。内存也不例外,但是由于二进制太长,我们用16进制来表示2进制
如:17CD = 0001 0111 1100 1101
我们一般用0x作为16进制的前缀,用来区分。
我们可以认为内存是连续的,就像一排屋子,所有的数据都会存储在这些屋子里。
我们都知道,每个屋子都有地址,那么所谓的指针就是这些屋子的地址
而这个地址里面存放的东西,就是这个变量的值
3.C语言中如何使用指针?
我们都知道*
这个符号是用来表示乘法,但是在C语言中,它还能表示定义指针和解引用
火锅有一锅三吃,符号也有一号三用
在不同的情况下,虽然都是*
,但是有不同的含义,现在我们至少知道3种含义:
- 乘法
- 定义指针
- 解引用
指针的基本使用方法:
int *p;
int x = 12;
p = &x;
我们说,这三句话分别表示:
- 定义了一个int类型的指针变量p
- 定义了一个int类型的变量x,并赋值12
- 将p赋值为(指向)x的地址
我们来解决一些问题:
- 为什么指针会有类型?
- 因为每个指针都有步长,不同的指针可以向后或者向前移动。int类型是32位(bit),4个字节(Byte)。
内存中是一个字节(Byte)为一个格子的,我们想让指针动一下,就得知道一个格子有多少位
- 因为每个指针都有步长,不同的指针可以向后或者向前移动。int类型是32位(bit),4个字节(Byte)。
- &符号是取地址的符号,也就是取到这个变量在内存中的地址。
输出指针
我们会用%p来输出指针的值
int *p;
int x = 12;
p = &x;
printf("%p", p);
我们会得到000000000061fe14这一串值,这个就是存下来的16位地址了
【间接引用】:
我们可以对指针进行解引用(拿到指针对应的值)
int *p;
int x = 12;
p = &x;
printf("%d", *p);
对一个已经是指针的数前面加一个*就是解引用,也就是拿到他的值
也可以用指针对原变量赋值
int *p;
int x = 12;
p = &x;
*p = 13; //这句话就等于 x = 13
printf("%d", x);
【练习题】
【关于“野指针”】
4.指针与数组
核心概念:数组名是数组第一个元素的地址,也是数组的首地址
int a[] = {1, 2, 3, 4, 5};
int *p;
p = a; // 语句1
p = &a[0]; // 语句2
因为数组名即数组第一个元素的地址,所以语句 1 和语句 2 是等价的,都是将数组 a 的首地址存放到指针变量 p 中。
【数组加减法】
当指针指向数组元素的时候,我们可以对指针变量进行加减运算,这样做的意义相当于指向距离指针所在位置向前或向后第 n 个元素。
比如 p+1 表示指向 p 指针指向的元素的下一个元素;p-1 则表示指向上一个元素。
需要郑重强调的是:p+1 并不是简单地将地址加 1,而是指向数组的下一个元素。
#include <bits/stdc++.h>
using namespace std;
int e[12];
int main() {
e[0] = 1;
e[1] = 2;
e[2] = 3;
e[3] = 4;
int *p = e;
p = p + 1;
printf("%d", *p);
}
【提高巩固习题】