0
点赞
收藏
分享

微信扫一扫

C++学习笔记(十八):指针【详细版】

唯米天空 2022-03-21 阅读 77

文章目录



1.什么是指针

指针就是内存地址,指针变量就是用来存放内存地址的变量。

总而言之,指针变量就是存放地址的变量,其指向的对象必须是变量,数组,函数等占有一定内存空间的实体。


2.为什么学指针

在C++中,指针的使用十分广泛。我们可以使用指针来写出更加高效,简洁的代码。


3.怎么使用指针

指针的定义:

指针的赋值:

指针的解引用:

我们来看一段代码:

#include <iostream>
using namespace std;
int main() {
int var = 6;
int* p_var = &var;
*p_var = 8;
cout<<" p_var ="<<p_var<<'\n'
    <<"  &var ="<<&var<<'\n'
    <<"*p_var ="<<*p_var<<'\n'
    <<"  var  ="<<var;
return 0;
}

运行效果如下:

 p_var =005CF714
  &var =005CF714
*p_var =8
  var  =8

由代码输出的内容可知:

我们来逐行分析一下:


4.指针的注意事项

4.1.指针的大小

我们知道,在C++中,存放数据的变量因数据类型不同,导致所占用的存储空间长度也不同。但需要注意的是,不同类型的指针变量所占用的存储单元长度是相同的。

如图所示:

指针大小.png

运行结果如下:

char类型的指针大小为:8
int类型的指针大小为:8
double类型的指针大小为:8

4.2.野指针

当出现以下三种情况时,我们称指针为野指针:

野指针的危害很大,如果野指针指向的空间正在被使用,或者指向的地址根本无法访问,这就会导致数据被破坏,程序出错甚至崩溃。因此我们应该避免野指针的出现。

5.二级指针

二级指针就是指针的指针

嘶,有点绕,这么说吧,二级指针里的存储的是一级指针的地址。也就是说二级指针是一种指向指针的指针

来看一段代码吧:

#include <iostream>
using namespace std;
int main()
{
int var = 6;
int* p_var = &var;
int** pp_var = &p_var;
cout << "&p_var = " << &p_var << '\n'
     << "pp_var = " << pp_var << '\n'
     << "变量var的值为:" << **pp_var;
return 0;
}

代码运行结果如下:

&p_var = 008FF8AC
pp_var = 008FF8AC
变量var的值为:6

输出语句验证了:

  • 二级指针里的存储的是一级指针的地址

代码分析:

还有一点需要注意:

6.指针与数组的联系

6.1.用指针访问数组

事实上,利用指针操作数组会比使用索引来操作数组更快一些。

来看一段代码:

#include <iostream>
using namespace std; 
int main ()
{
int  arr[3] = {19,45,37};
int  *p;
p = arr;
for (int i = 0; i < 3; i++)
{
cout<< "arr[" << i << "]的内存地址为 "
    << p << endl
    << "arr[" << i << "] 的值为 "
    << *p << endl;
p++;   
}
return 0;
}

运行结果如下;

arr[0]的内存地址为 0x6ffdf0
arr[0] 的值为 19
arr[1]的内存地址为 0x6ffdf4
arr[1] 的值为 45
arr[2]的内存地址为 0x6ffdf8
arr[2] 的值为 37

在上述代码中,有三条语句引起我们注意:

我们来分析一下:

再来看一段代码:

#include <iostream>
using namespace std; 
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9};
int* p1 = arr;
int* p2 = &arr[4];
cout<<"p2-p1 = "<<p2-p1;
return 0;
}

输出结果为:

p2-p1 = 4

我们的结论是:


6.2.注意事项

一:避免出现野指针

二:不能修改数组地址


7.NULL指针

NULL指针是一个定义在标准库中的值为零的常量

看代码:

#include <iostream>
using namespace std; 
int main ()
{
int* p = NULL;
cout<<"空指针的值是 "<<p;
return 0;
}

运行结果为:

空指针的值是 0

小结:

当我们把未使用的指针都赋值为NULL时,我们就可以使用if语句:if(p!=NULL)判断指针是否不为空如果不为空,再进行指针操作,这能有效地避免使用未初始化的指针。


8.数组指针与指针数组

8.1数组指针

来看一段代码:

#include <iostream>
using namespace std; 
int main()
{
int arr[5]={16,75,31,65,82};
int *p = arr;
for(int i=0;i<5;i++)
{
	cout<<*(p+i)<<" ";	
}
return 0;
}

运行结果如下:

16 75 31 65 82

分析:


现在,我们来看看指向二维数组的数组指针

代码如下:

#include <iostream>
using namespace std; 
int main()
{
int arr[3][4]={{11,16,24,28},{36,41,48,53},{66,88,90,98}};
int (*p)[4] = arr;//定义了一个数组指针,且指向了二维数组 
for(int i=0;i<3;i++)
{
    for(int j=0;j<4;j++){
    	cout<<*(*(p+i)+j)<<"  ";	
	}
    cout<<'\n';
}
return 0;
}

运行结果如下:

11  16  24  28
36  41  48  53
66  88  90  98

分析:

还有一点很有意思:


8.2.指针数组

我们将元素全是指针的数组称为指针数组

并且数组里的指针是指向相同数据类型的指针

来看一段代码:

#include <iostream>
using namespace std; 
int main()
{
int a1[3] = {1,2,3};
int a2[3] = {1,2,3};
int a3[3] = {1,2,3};
int *p[3] = {a1,a2,a3};
for(int i=0;i<3;i++)
{
	for(int j=0;j<3;j++){
		cout<<p[i][j]<<" ";
	}
	cout<<'\n';

}
return 0;
}

运行结果如下:

1 2 3
1 2 3
1 2 3

指针数组本质上是一个数组

指针数组常用于指向若干字符串,这会使字符串处理更加灵活方便,也更加节省内存空间

实例:

#include <iostream>
using namespace std; 
int main()
{
char *p[] = {"Hello ","World!"};
for(int i=0;i<2;i++)
{
	for(int j=0;j<6;j++)
	{
		cout<<p[i][j];
		//也可以用 *(*(p+i)+j)
	}
}
return 0;
}

运行结果如下:

Hello World!

9.函数指针与指针函数

先看定义:

函数指针与指针函数区别在于


9.1.函数指针

声明语法:

赋值语法(两种):

需要注意的是:

来看段代码

#include <iostream>
using namespace std;
int sum(int x, int y) { return x + y; };
int main()
{
	int (*ptr)(int, int);
	ptr = sum;
	int a = 3, b = 3;
	int c = (*ptr)(a, b);
	cout << "c的值为:"<<c;
return 0;
}

运行结果如下:

c的值为:6

分析:

总结:


9.2.指针函数

声明语法:

来看段代码

#include <iostream>
using namespace std;
float *find(float(*p_func)[3],int n) /*定义指针函数*/
{
	float *p_new;
	p_new = *(p_func+n);
	return p_new;
}
int main(void)
{
    static float score[][3]={{96.3,89.7,66.9},{85.1,89.2,87.5},{66.3,59.8,76.4}};
    float *p;
    int m;
    cout<<"您想查找第几位同学的成绩(共三位):\n";
    cin>>m;
    cout<<"第"<<m<<"位同学的语数英成绩分别为:\n|" ;
    p=find(score,m-1);
    for(int i=0;i<3;i++)
    	cout<<*(p+i)<<" |"; 
    return 0;
}

运行结果为:

您想查找第几位同学的成绩(共三位):
1
第1位同学的语数英成绩分别为:
|96.3 |89.7 |66.9 |

分析:

总结:


10.函数指针数组

顾名思义,函数指针数组就是存放函数指针的数组

函数指针数组的用法就有点像点菜单一样,我们在数组里面存放若干个函数指针,然后让用户来选择使用哪些函数数组中的指针可以用来调用函数。

来看段代码:

#include <iostream>
using namespace std; 
int get_sum(int a,int b)
{
	return a+b;
}
int get_sub(int a,int b)
{
	return a-b;
}
int main()
{
int (*p[2])(int,int)={get_sum,get_sub};
int opt;
cout<<"请选择运算(加法为0,减法为1):\n";
cin>>opt;
int x,y;
cout<<"请输入参与运算的数值:\n";
cin>>x>>y; 
cout<<"运算结果为:"<<(*p[opt])(x,y);
return 0;
}

运行结果如下:

请选择运算(加法为0,减法为1):
0
请输入参与运算的数值:
2
4
运算结果为:6

分析:

一:int (*p[2])(int,int)={get_sum,get_sub};

二:cout<<"运算结果为:"<<(*p[opt])(x,y);


11.this指针

在C++中:

注意!:

this指针的某些使用情景:


好了,指针部分的学习就到这了,可能有些晕(我之前也好晕),看不懂就多看几遍,并学会运用,相信指针部分是能够完美搞定。按照惯例,最后再来张思维导图梳理一下吧。

举报

相关推荐

0 条评论