☰
最绚丽的星星-指针
2026/10/14 1:39:45 网站建设 项目流程

前言:如果觉得文章对你有帮助的话,请点赞收藏关注支持一下博主😍,如有不足请指点,我及时改正!👻一起加油!

我们知道内存是按字节排列的内存空间,每个字节有一个编号,称为“地址”,

程序用到的数据和声明的变量就存放在这一个个字节中,不同类型的数据和变量占用的字节数不同。

习惯上,将某个变量占用的几个字节称为内存单元。

通过变量名可以访问该变量对应的内存单元,实际上,我们也可以直接通过地址来访问某个内存单元。

(我认为这个解释很形象,这里就直接粘过来用了嘿嘿)🤣

1.声明一个指针变量

指针和int,float一样,也是一种数据类型。

基于该数据类型声明的变量称为指针变量。

而“区别于“int这种数据类型存储的是数值,指针变量存储的是内存中的某个地址。

和普通的变量一样,在使用指针变量之前应先对指针变量进行声明。

类型* 指针变量名; //如 int* p;
//说明,写成int* p;或int *p;都是可以的,*跟着谁都行
*在这里表明这是一个指针变量,类型指定了指针所指的内存单元的数据类型。

注意⭐,

int* p1, p2;
//声明了一个指针变量p1和int型变量p2
一次性声明多个指针变量时,每个指针变量名前都要加*
例, int* p1,*p2; //这样才是声明了两个指针变量p1,p2

下面我们来看一个程序。

#include <iostream> using namespace std; int main() { double num = 3; double* pNum; pNum = &num; cout << "pNum在内存中的地址是:" << &pNum << endl; cout << "pNUm的值为:" << pNum << endl; cout << "num在内存中的地址为:" << &num << endl; cout << "使用指针访问num:" << *pNum << endl; cout << "pNum(指针类型)在内存中的字节数:" << sizeof(pNum) << endl; cout << "num(double型)在内存中的字节数:" << sizeof(num) << endl; return 0; }

可能你会有疑问,这里指针的数据类型不是double型吗,怎么占用4个字节?

答:指针变量存储的内容是内存中某个字节的地址,指针变量占用的内存字节数随系统的不同有所不同,在普通的Windows32平台上,指针变量占4个字节,但在其他一些内存模型中,指针变量可能占用 两个字节,简单地说,指针变量占用的字节多少取决于程序的内存空间有多大。

如下图,

代码解析:

1.double num=3;
声明了一个double型变量num,并对其赋初值为3,
编译器将在内存中开辟一块8个字节的区域,将num和这8个字节关联起来,并将这8个字节初始化为3。

2.double* pNum声明了一个指向double类型的指针
编译器将在内存中开辟一块4个字节的内存区域,并将其和pNum关联起来

3.pNum = &num;是对指针变量的赋值,&是取地址运算符,意思就是,将num这个变量的地址赋值给pNum变量(指针变量存储的是地址呀)

4.⭐可通过"指针变量名"对指针所指向的内存单元来进行访问 这里的可不是之前发挥的 表明 这是一个指针的作用了,而是要理解为间接引用符(也就是我们说的解指针) 这里对*pNum的访问和通过变量名(num)对该内存单元的访问实际是一样的都是对005DFC58-005DFC5F这8个字节进行访问。见下图。


2.初始化指针变量

⭐野指针是大坑!使用指针前必须初始化!!

  1. 未初始化的指针是什么?

当你仅仅声明指针变量,却不给它赋值的时候,C++不会自动帮你初始化。 指针变量里会存内存里残留的随机地址,这种指针我们叫野指针。

野指针会随便指向一块未知内存,如果直接用*去访问它指向的内容,程序行为完全不可预测,大概率直接崩溃,属于非常危险的操作。

代码演示如下:

#include <iostream> using namespace std; int main() { int *p; // 只声明指针,没有初始化!p里面是内存随机垃圾值(野指针) *p = 100; // 致命错误!解引用野指针,向未知内存写数据 return 0; }

2.正确初始化指针:声明时直接绑定变量地址。

通过取地址符(&)给指针变量赋值是个有效的手段,实际上,可以在声明一个指针变量的同时完成其 初始化。

int num=1; // 先开辟一块内存,存放整数1
int* p=&num;// 定义int类型指针p,把num的地址存入p

代码如下:

🎈1>声明同时初始化

#include <iostream> using namespace std; int main() { int num = 1; int* pN = &num; // 定义指针同时绑定num的地址 *pN = 100; // 修改pN指向的num变量的值 cout << num << endl; // 输出100 return 0; }

🎈2>暂时不知道指向谁 → 初始化为空指针

#include <iostream> using namespace std; int main() { int* p = NULL; // 空指针:明确表示不指向任何有效内存 // *p = 200; // 禁止!空指针也不能直接解引用,依然会崩溃。空指针不等于安全指针奥 return 0; }

3.一条铁则:使用间接引用*之前,指针必须有合法指向

在你打算用*指针去读写内存前,一定要保证指针已经初始化,指向一块合法有效的内存。

如果暂时不知道这个指针要指向谁,不要放任它变成野指针,手动赋值为空指针:NULL(值等价于 0),代表 “无处可指”。

int* p = NULL; // 空指针:不指向任何有效内存


3.指向指针的指针(二级指针)

指针本身也是变量,变量就有内存地址。既然有地址,我们就可以用另一个指针保存这个地址,这就是二级指针。

声明格式:基础类型 **变量名.


普通一级指针:类型*,存放普通变量的地址。

二级指针:类型**,存放一级指针变量的地址。

double num; // 普通double变量
double* pN = &num; // 一级指针pN:存放num的地址
double** ppN = &pN; // 二级指针ppN:存放一级指针pN的地址

代码演示如下:

#include <iostream> using namespace std; int main() { double num = 3.14; double* pN = &num; // 一级指针,指向num double** ppN = &pN; // 二级指针,指向一级指针pN cout << "num的值:" << num << endl; cout << "num的地址:" << &num << endl; cout << "pN的值(存放num地址):" << pN << endl; cout << "pN自身的地址:" << &pN << endl; cout << "ppN的值(存放pN的地址):" << ppN << endl; // 解引用 cout << "*pN :" << *pN << endl; // 取pN指向内容,就是num的值 cout << "**ppN:" << **ppN << endl;// 对二级指针两次解引用,最终拿到num的值 return 0; }

  • *ppN:对二级指针解一层引用,拿到一级指针 pN(等价 pN)

  • **ppN:连续两层解引用,顺着ppN→pN→num,拿到最终变量 num 的数据

易错提醒:

double** ppN = &pN;
// ❌ 错误写法: double** ppN = &num;
// ppN 是 double** 类型,只能接收 double* 类型变量的地址,不能直接存普通变量num的地址!

类型必须匹配:

  • double*只能保存double变量地址

  • double**只能保存double*(一级指针)变量地址


总结

希望可以帮助到大家,感谢观看,下篇讲解指针赋值,指针运算,动态内存的问题,想看的小伙伴码住,嘻嘻😜

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询