[置顶] “指针的爱情故事”(指针\多级指针 详解,常量指针\指针常量\常量指针常量,数组指针\指针数组,函数指针\指针函数)

时间:2021-12-28 04:41:46

“指针的爱情故事”(指针\多级指针 详解,常量指针\指针常量\常量指针常量,数组指针\指针数组,函数指针\指针函数)

作者:谭丙章(AlexTan)
E-mail: alextanbz@gmail.com
注:转载不贴上作者信息以及原文地址,必追究其法律责任

因为最近要讲课的原因,想着怎么才能让学弟学妹们把指针理解透,学指针学起来不枯燥。于是自己编写了 ”指针的爱情故事“。

先声明:此故事纯属虚构,如有雷同,不胜荣幸!

故事以及讲解都在代码注释里,所以就直接上代码:

#include<iostream>
using namespace std;
/*-------------------------------------------指针的爱情故事---------------------------------------------*/

//讲故事前,首先,介绍一下地址的概念 ps:其实地址就是变量的家啦~! 和人类世界不同的是,变量的整个一生都会待在家里!
void address()
{
int baby; //一个叫baby的int类型的变量出生了,上帝会给他在栈区分配一个家(地址)。这里的专业名字叫:声明! 知识拓展一:局部变量的家(存放位置)是在栈区,全局变量和static变量的家(存放位置)在全局数据区。
//我们来看一看baby是在什么地方出生的!
cout << &baby << endl; //给baby加上“&”(取地址符),就能找到去baby家的路
baby = 1; //经过成长的磨练,baby长大啦!他有了自己的个性,包括价值观、爱情观、性格等等(用1来代替)。 这里的专业名字叫:定义!
//我们来看看baby的性格、价值观、爱情观是怎样的
cout << baby << endl;
}

/*有了地址的概念,那么我们就开始来讲讲指针,指针也许是计算机世界里最痴情的人~,就好像人类世界里的“了不起的盖茨比”。*/
//首先是指针变量
void pointer()
{
int *Gatsby; //盖茨比出生了,同样,上帝也会给他在栈区分配一个家(地址)。
char baby;
int lover; //同时,另外两个小孩儿也出生了
//我们来看看盖茨比的家在哪
cout << &Gatsby << endl;
//盖茨比小时候,也以为自己和其他小孩儿(变量)一样
baby = 'a';
lover = 2;
//*Gatsby = 1;
//cout << *Gatsby << endl;
//一次碰壁后,他才知道他与众不同!他在人生的道路上不断地寻找自己,通过他的努力,终于找到了正确的道路
Gatsby = new int(1); //知识拓展二:new int(1)代表从堆中给Int类型的值“1”(可以理解成结果等于1的Int类型变量)分配一个空间
cout << *Gatsby << endl;
//同时,他还有了一个惊奇的发现
cout << Gatsby << endl; //他发现自己可以找到别人的家(地址)。
//于是,他渐渐长大了,看了很多悲剧性的爱情电影,那时他就发誓,自己将来一定要好好对待一个女孩儿!懵懂的爱情在他脑中荡漾~。最开始,他遇到了baby,渐渐喜欢上了她,于是他向她表白了。
//*Gatsby = baby; //我喜欢你。。。一开始就被狠狠地拒绝了,可是,他不是那种轻易放弃的人
//Gatsby = baby; //结果,他直接在全班同学面前出糗了,很尴尬~! 于是他就开始反思,也许是他方法用得不对,于是他又去寻找不同的方法
//*Gatsby = &baby; //还是惹来同学的笑话
//Gatsby = &baby; //一次次地失败,最终把他打击得实在是没有信心了....于是他就想:“也许他们俩根本就不适合!”
//他放弃了baby... 果然,没过多久,他就遇到了另外一个女孩儿,并且是一见钟情!他有了上一次的经验,一下就找准了方法
*Gatsby = lover; //我喜欢你... 批注:这里只是给指针赋值,把lover的值赋给指针,并没有让指针指向lover
cout << &lover << endl;
cout << Gatsby << endl;
cout << *Gatsby << endl;
Gatsby = &lover; //渐渐的...我喜欢你,变成了我爱你...盖茨比把lover的家,lover的个性都深深地烙印在了自己的心底。 批注:指针指向lover。
cout << &lover << endl; //lover的家
cout << Gatsby << endl; //lover的家
cout << *Gatsby << endl; //lover的个性
lover = 3; //即使lover的个性或者是外貌改变了,盖茨比也始终爱着她
cout << *Gatsby << " " << lover << endl;
*Gatsby = 4; //lover或许是因为盖茨比的爱而感动,或许是因为其他,lover也爱上了盖茨比
//他们形影不离,你变我也跟着变,彼此都住在对方的心底
cout << *Gatsby << " " << lover << endl;
}

//尽管盖茨比他们彼此已经非常非常相爱了,但是,现实最终打败了他们,不过,盖茨比却得到了升华~
void multipointer()
{
int lover = 2;
int *Gatsbyago=&lover; //以前的盖茨比只是纯粹的爱上lover。知识拓展三:声明这里初始化可以这样写,其他地方必须得这样写:Gatsbyago=&lover,代表Gatsbyago指针指向lover。
//知识拓展四:如果指针未被初始化(未指向一个地址),那么也不能进行*Gatsbyago = 3 之类的操作,指针本身的地址只能指向一个地址,不能存放普通值。
int family=3;
int *lovers = &family; //lovers爱自己的家人
int **Gatsbynow; //如今的盖茨比
cout << &lovers << " " << &family << " " << lovers << " " << &Gatsbynow << endl;
Gatsbynow = &lovers;
cout << **Gatsbynow << " " << *Gatsbynow << " " << Gatsbynow << " " << &Gatsbynow << endl;
//如果family改变,其他所有人都跟着改变
family = 4;
cout << family << " " << *lovers << " " << **Gatsbynow << endl;
//如今的盖茨比,不仅爱着lovers,他还爱着他爱人所爱的所有人。正所谓:爱屋及乌...
/*-----------------------------END------------------------------*/
//*Gatsbynow = &lover; //知识拓展五:清楚二级指针 **xxx(二级指针所指向的“一级指针指向的地址的值”),*xxx(一级指针所指向的地址),xxx(一级指针的地址)代表什么后,可以进行篡改操作,这样的篡改同时会把lovers一级指针所指向的地址改变(即,盖茨比的爱人爱的人变了,他所爱的人同样跟着变)
//cout << family << " " << *lovers << " " << **Gatsbynow << endl;
//多级指针同理
}

/*------------------------常量指针、指针常量、常量指针常量------------------------*/

void ConstPointer()
{
const int a = 1; //常量变量
//a = 2; //非法操作:常量不能被改变
int b = 2;
int c = 3;
const int *pointer = &a; //常量指针,是一个指针,即可以理解为指向常量的指针,常量的值不能变,指针指向的地址可以变
//*pointer = 4; //非法操作
//pointer = &b; //合法操作
int const *pointer2 = &b; //常量指针的另外一种声明方式
//*pointer2 = 4; //非法操作
//pointer2 = &c; //合法操作
int *const pointer3 = &c; //指针常量,是一个常量,即可以理解为指针是常量,指针指向的地址的值可以变,指针指向的地址不可以变,
//*pointer3 = 4; //合法操作
//pointer3 = &b; //非法操作

const int *const pointer4 = &a; //常量指针常量,全都是常量,不管是指针指向的地址,还是值都不能被改变
//*pointer4 = 8; //非法操作
//pointer4 = &b; //非法操作
}

/*------------------------------------数组指针、指针数组---------------------------*/

void ArrayPointer()
{
//顾名思义,数组指针:是一个指针,这个指针是指向数组的指针;指针数组:是一个数组,这个数组是存放指针(地址)的数组
int *a[4]; //指针数组
cout << &a << endl;
int b[4] = { 1, 2, 3, 4 };
//给指针数组赋值
for (int i = 0; i < 4; i++) // int
{
a[i] = &b[i];
}
//输出:
for (int i = 0; i < 4; i++)
{
cout << *a[i] << " ";
}
cout << endl;
int (*c)[4];//数组指针
c = &b; //数组指针指向b这个数组
//输出:
for (int i = 0; i < 4; i++)
{
cout << (*c)[i] << " ";
}
}

/*------------------------------指针函数、函数指针-------------------------*/

int *f1(int a, int b) //指针函数
{
int *c;
if (a > b)
{
c = &a;
cout << &a << endl;
return c;
}
else
{
c = &b;
cout << &b << endl;
return c;
}
}
int(*f2)(int a, int b); //声明函数指针
int max(int a, int b) //普通函数
{
if (a > b)
return a;
else
return b;
}
void FuncPointer()
{
//同样,顾名思义,指针函数:是一个函数,不过这个函数返回的类型是一个指针;函数指针:即是一个指针,不过这个指针指向的是一个函数
int a = 1, b = 2;
cout << f1(a,b) <<endl; //调用指针函数,输出的是地址,如果输出 *f1(a,b) 将输出值。
f2 = max; //函数指针指向max函数
cout << (*f2)(a, b) << endl; //通过函数指针调用函数
}

/*----------------------------------主函数----------------------------------*/

int main()
{
//address(); //地址
//pointer(); //一级指针
//multipointer(); //多级指针
//ConstPointer(); //常量指针、指针常量、常量指针常量
//ArrayPointer(); //数组指针、指针数组
//FuncPointer(); //函数指针、指针函数
return 0;
}

建议不懂的同学把代码一步一步调试一下,如果还有什么不懂的欢迎评论留言!

最后留下一句话(ps:也是自己编的):

程序猿的我爱你,是像指针那样,爱你胜过爱自己,把两个地址都连在了一起,有了你,我才有存在的价值;如果你爱着别人,那么我就是多级指针,爱你所爱的人,当然包括你~!