目录
一、内存是什么?
1.1、内存
内存就是计算机内部的储存空间(废话文学??),类比于你的书架,你的钱包,你家的仓库等等,它们用于储存你放的东西;
内存包括内存地址和储存空间;就像你去图书馆,要查找书的地址(内存地址),再通过书的地址找到书在哪儿,再看书(访问内容);
(来看灵魂画手!)
我们来定义一个整型变量int c=999;
计算机会这么分配内存空间:
(老子早晚要搞台IPAD来学画画。。。)
1.2、变量地址;
你看,我们知道了c的地址被储存在1的位置(真实的地址都是形如0161FD51一样的,这里只是形象地说明所以我们采用了1的说法);1就是起始地址;那么,我们怎么拿到变量c的地址呢?
你一定想到了吧!我们使用取值符“&”来获取变量地址!请看:
#include<bits/stdc++.h>
using namespace std;
int main(){
int c=999;
cout<<"c: "<<c<<endl;//输出c的值
cout<<"&c: "<<&c<<endl;//输出c的地址
}
&c就是变量地址,也就是我们要找的“书的位置”;
二、指针
2.1、夏日
那年夏夜我们在83-Lounge喝金汤力和椰林飘香,杜松子的气味很清,就像你身上的潘海利根琴酒;你好奇我一个小孩子怎么会来这里,我好奇你为什么来逗一个小孩子开心;我记得你跟我开的玩笑,男孩子该试试马天尼,敢试我就给你份惊喜;
小孩子那么倔怎么会拒绝?小孩子怎么会承认自己是小孩子?
于是我晕乎乎地拿到人生中第一张写有电话号码的纸条;
或者说,一根独特的指针,指向一个我不清楚的值;
没错亲爱的朋友们,那张纸条就是个指针,我可以借助这个指针(这张写有电话号码的纸条)来找到那个姐姐(变量)。
那么C++中的指针呢?
2.2、指针
接下来我们将声明一个指针变量,它将指向一个整形变量;
请看:
#include<bits/stdc++.h>
using namespace std;
int main(){
int July=166;
int *July_num = &July; //July_num为指针,它的值是July的地址;
}
然后再看看灵魂画手!
是的,您可以看到,July_num是个整形指针变量,它指向的是整形变量July的起始地址1(哈哈哈当然真实的地址不是这样的啦,真实的地址是0x71fe00这样的形式,只是方便理解我写成了1喔);
对于 int *July_num = &July; 它是把July的地址1赋给了指针July_num;
让我们看看输出吧!
#include<bits/stdc++.h>
using namespace std;
int main(){
int July=166;
int *July_num = &July; //July_num为指针,它的值是July的地址;
cout<<"July_num = "<<July_num<<endl;
}
July_num便是那张写有电话号码的纸条!(记录了July的地址1)
而July就是那位漂亮姐姐!!(可以通过修改*July_num的值来修改July的值,我们稍后再讲)
简而言之就是,
*指针是一种值为地址变量,存的是内存的地址编号。
2.3、*July_num与July_num;
两者并不是一回事!!
请看:
#include<bits/stdc++.h>
using namespace std;
int main(){
int July=166;
int *July_num = &July; //July_num为指针,它的值是July的地址;
cout<<"July_num = "<<July_num<<endl;
cout<<"*July_num = "<<*July_num<<endl;
*July_num=199; //如您修改*July_num,July亦会一并修改;
cout<<"July = "<<July<<endl;
}
您可以看到July_num的值是一个地址,而 *July_num是一个值;
而通过指针修改的值会一并修改原来的值;
2.4、指针的赋值与类型
您看,July_num就是一种指针,而赋值的类型必须是相同的,您不能把一个数字赋给一个地址对吧,所以形如 July_num = 999 是错误的,正确的赋值是使用取址符&,即
July_num = &July;
除此之外,您可以定义其他类型指针如下;
#include<bits/stdc++.h>
using namespace std;
class Sum_mi {
public:
char Name;
int Hight=160;
int Weight=55;
}; //定义类为 Sum_mi;
int main(){
double* Judy_num;//指向double类型的指针
char* Angel_num;//指向char类型的指针
bool* Annie_num;//指向bool类型的指针
Sum_mi* Sum_mi_num;//指向类或者结构体类型的指针;
int** Badguy_num; //指向 int*的指针,也称二级指针;
}
需要特别提到的是空指针和void指针;
空指针:不指向任何东西的指针,可以赋予一个整形的0给指针,使其变成空指针,也可赋值NULL使其变成空指针;如:
#include<bits/stdc++.h>
using namespace std;
int main(){
if(NULL==0)cout<<"yes"<<endl;
char* P_NULL1=0;
char* P_NULL2=NULL;
cout<<"* P_NULL1 = "<<* P_NULL1<<"yes"<<endl;//如果是它们是空指针,那么这两句话不会被执行;
cout<<"* P_NULL2 = "<<* P_NULL2<<"yes"<<endl;//您可以以此检验指针是否为空指针;
}
void*指针:可以接受任何类型的地址;
请看:
#include<bits/stdc++.h>
using namespace std;
int main(){
char Sum_mi='J';
char *Sum_mi_p = &Sum_mi;//普通指针必须严格对应类形;
//char指针只能接受 char的变量;
void* Sum_mi_p1 = &Sum_mi;//void指针可以接受任何类型;
cout<<"Sum_mi_p"<<Sum_mi_p<<endl
cout<<"Sum_mi_p1"<<Sum_mi_p1<<endl;//可以看出来它们均能输出;
}
2.5、数组名也是一种特殊的指针?!!
还真是。。。。。。请看:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[5]={1,2,3,4,5};
//数组名称本来就是一种指针;
for(int i=0;i<5;i++)
{
cout<<a+i<<endl;
}
//您将看到数组a的每一个元素的地址;
for(int i=0;i<5;i++)
{
cout<<*(a+i)<<endl;
}
//您将看到数组每一个元素的值;
}
2.6、指针的指针——二级指针;
指针当然也可以指向指针!
指针当然也可以指向 指向指针的指针!
指针当然也可以指向 指向的指向指针的指针!
(我不喜欢套娃但是经常得跟套娃打交道。。。呜库鲁西。。。)
#include<bits/stdc++.h>
using namespace std;
int main(){
int c=999; // 定义整形变量c,值为999
int* pc=&c; //定义整形指针pc指向c,指针型变量的储存对象为地址; &c为获取c的地址;
cout<<pc<<endl; //输出指针pc的值,也就是c的地址;
cout<<*pc<<endl;//输出指针pc所指向的c的值;可以对其进行运算操作等等,会直接改变c的值;
*pc-=999; //对*pc进行操作;
cout<<*pc<<" "<<pc<<" "<<c<<endl; //通过指针pc对c进行操作,进而传递值;注意,c的值会改变,但是pc的值,也就是c的地址不会改变;
int **ppc=&pc; //指针当然可以指向指针;此为二级指针;
cout<<ppc<<" "<<*ppc<<" "<<**ppc;
//输出二级指针ppc的地址;
//输出二级指针*ppc指向一级指针*pc的地址;
//输出二级指针ppc最终指向的值;
}
}
三、尾声
感谢您的阅读!
笔者只是一名普通的大学生,因此行文与观点多有不成熟之处,
受限于笔者的水平,本文并不包括数组与指针的讲解;
如果您有独特的观点与想法,欢迎与我讨论,还望您不吝赐教,我将十分感激;
如本文有疑似侵犯版权的问题,请与笔者速速联系!
您可以给我留言,(虽然我怀疑没什么人看?)看到我会尽快回复;
本文不含例题(就是笔者是个贱人他懒得找所以放在下次一并讲了哈哈哈)
下一篇文章将讲解链表,使用acwing的题目作为例题讲解;
特别鸣谢Hasmokan,
Krito,AC-47亦对本文有指导。
夏日弥死傲娇
于2021.11.14