C/C++指针总结(上)---超详细,看不懂打我!!

一、什么是指针?

想必大家在初学指针的时候,都会感觉指针很神奇,但是对指针又不是很了解,而且指针的内容很多,很杂。于是,在学完指针后,我进行了总结。

(1)那什么是指针呢?

指针其实就相当于是地址,指针分为常量指针和变量指针.
指针变量:其他的变量类似,可以随时改变其中的值。只不过这个变量存储的是地址
谈到地址,我们平常写的数据,变量,在计算机中都是以字节为单位进行存储的,一个字节对应一个地址。
所以指针就是保存这些变量的地址,然后通过地址来访问数据。
常量指针(在下一篇总结有详细讲到,所以这里的指针都是指的是变量,简说为指针)
在这里插入图片描述
这里int a占4个字节,如果用指针 int *p=&a;p存储的是a的首地址。

(2)了解几个术语

1.定义:声明一个变量,但不赋初值
2.初始化:对声明的变量赋值
3.指向:如果指针保存的整形变量的地址,我们就说指针指向这个整形变量
4.解引:得到指针指向地址的值.

int a=10;
int *pr=&a;
cout<<*pr<<endl;//*pr相当于10

这里*pr就是取的pr中的值,注意:int *pr中的 pr和 后面的pr 不同,前者是定义一个指针,后者是得到a的值

(3)指针如何定义呢?

指针定义和其他变量定义类似。

定义并初始化变量(定义:int a; 初始化: a =10)

int  a =10;
double b=10.0;

定义并初始化指针变量

int *P1=NULL;//定义一个指向整形的指针(指针p保存的是整形变量的地址)
double *p2=NULL;//指向双精度的指针

*的位置没有要求,可以int* p1,int *p1,int*p1,但为了美观,个人推荐int *p1这种形式。注意如果我门声明int* p1,p2;
p1是指针,而p2是int类型的变量。我门应该写成int *p1,*p2;

这里指针等于NULL(0),是给指针进行初始化,后面会详细讲解

扫描二维码关注公众号,回复: 11332476 查看本文章

二、为什么要使用指针?

有人会问,我们可以直接访问变量呀,为啥还要么先定义指针来获得地址,再通过地址访问变量,这样不是很多余吗?

确实如此,但是指针自然有它的妙处

(1).函数的值传递,无法通过形参来改变实参的值

比如我们交换两个数

void swap(int a ,int b){
	int temp=a;
	a=b;
	b=temp;
int main(){
	int x=1;
	int y=0;
	swap(x,y);
	cout<<x<<" "<<y;
}

会发现在main函数中x和y的值并没有改变
原因:其实是在声明形参a和b时,只是把x和y值的拷贝给了a和b。栈为a和b重新分配了内存空间,交换的只是a和b的值
(这里不懂什么是栈空间的可以看我之前写的c++、c内存分配
[c++内存分布](https://blog.csdn.net/weixin_46273997/article/details/105268061)

那怎样解决呢?
我们可以用指针或引用
指针版:

void swap(int *a ,int *b){
	int temp=*a;
	*a=*b;
	*b=temp;
int main(){
	int a=1;
	int b=0;
	swap(&a,&b);
	cout<<a<<" "<<b;

`会发现这里a和b的值就交换了,因为我们传入的是a和b的地址,即指针指向a和b的内存地址,这样通过指针,就能交换。

引用版:

void swap(int &a ,int &b){
	int temp=a;
	a=b;
	b=temp;
int main(){
	int a=1;
	int b=0;
	swap(a,b);
	cout<<a<<" "<<b;

(引用后面会讲到)

(2).有多个返回值

函数的返回值只能有一个,但使用指针可以有多个返回值,所谓多个返回值并不是

int swap(int a,int b){
	int temp=a;
	a=b;
	b=temp;
	return a,b;
}

而是指的是,我么传入多个地址到函数中,对传入的地址进行操作,就相当于返回多个返回值,比如

bool add_blood(int *blood){
	if((*blood)>=1000){
		*blood+=1000;
	}
	return true;
}
int main(){
	int blood=1000;
	if(add_blood(&blood)){
		cout<<"加血成功"<<endl;
	}
	else{
		cout<<"加血失败"<<endl;
	}

}

这里我们返回了true的同时,又改变了blood 的值;

(3).减少值传递带来的额外开销,提高代码效率

比如我们在用形参接收实参时,尽可能使用指针会减少内存的使用。
这里补充一个小知识:即指针的所占的内存是固定不变的,不管是什么类型的指针,所占的字节数不变,具体是多少有系统决定,一般32位系统占4个字节,64位系统占8个字节

所以我们用指针作形参能节省空间,比如形参接收一个结构体,那么会在栈空间上开辟一个相同大小的内存来存储,但是如果我们使用结构体指针,这样就会节省内存空间

#include <iostream>
#include <string>

using namespace std;

struct student{
	int age;
	char sex;
	string name;
};

void change(struct student b){
	b.age=19;
	b.sex='m';
	b.name="如花";
}
void change(struct student *b){
	b->age=19;
	b->sex='m';
	b->name="如花";
}

int main(){
	struct student a;
	a.age=18;
	a.sex='f';
	a.name="秋香";
	change(a):
	change(&a);
	return 0;
}

这里a占多少字节可用sizeof(a)计算,change(a),就相当于main函数中中有一个结构体,然后change函数中又有一个结构体,这样不是浪费了内存空间? 相反如果我们使用指针,效率就更高了

三、指针的分类

野指针,函数指针,数组指针,指针数组,指向常量的指针,指针常量,数组的指针,结构体指针,特殊的指针--引用将在下一篇文章中进行介绍
这里先简单介绍一下野指针
所谓野指针就是你定义了一个指针,但并没有为它初始化,这类指针就叫野指针.如果不初始化,里面存储的地址是随机的,不清楚是什么,如果后面使用了这个没初始化的指针,可能会造成的后果,所以大家记住申明指针时一定要初始化哟!

下一篇文章会介绍其他类型的指针
传送门

最后附上一个学院的b站二维码,里面很多视频是免费的,有很多大佬为你解答疑惑,还有很多活动,大家可以在这里进行交流

猜你喜欢

转载自blog.csdn.net/weixin_46273997/article/details/105449959