C/C++—指针基础小结

C/C++—指针基础小结


想必大多数正在学、学过C语言的人都有个体会:指针确实不好学。不仅是因为其本身奇怪的定义,也因为对于许多开发者(例如我)来说,如果不从事硬件开发、操作系统开发、C/C++方面的开发的话,指针的用处确实不大。且指针属于C/C++独有的内容,如果习惯使用其他语言进行工作,哪怕曾经学了指针,也会“用进废退”。
近来由于备战一些考试和竞赛,加之时不时被学弟学妹们问的一些问题哽住,便痛下决心,重新梳理一遍指针。也许内容不是太全,主要适用于为本科阶段计算机的学习打基础。

1.为什么要提出指针/什么是指针

前面提及,指针是C/C++的独有内容,指针的产生也与这两门语言本身的特性有关——偏底层。相比起如Java、Python、C#等其他语言,C/C++更多地支持对硬件、操作系统的控制。
从本质上来说,指针是用于操作内存的。关于内存、数据存储等概念,在此不作概述。现在我们要明白的一个核心概念就是,指针的作用是访问程序中的变量存在电脑中的地址

2.指针的相关定义及性质

2.1指针的运算

指针独有的两个运算符如下:

*
&

其中第一个“*“用于定义指针变量,“&”用于取地址;两个符号互为逆运算。

2.2指针变量的定义及使用

指针变量的定义方法:
数据类型 *变量名;
例如如下代码:

int *a;//定义变量a为一个nt类型的指针变量

那么如何体现指针对地址的操作呢?我们看如下代码:

#include<iostream>
using namespace std;
int main() {
	int *a; 
	cout<<a<<endl;
	return 0;
	}

程序输出为0x191380。很明显,这是计算机中的一个地址值,由于已经定义了a为指针变量,直接输出便是读取了其地址值。
以上为“*”操作符的一个运行示例,那么“&”取地址符又是怎么用呢?
指针变量名 =&被取地址的变量名;
我们来看一下两段代码:

#include<iostream>
using namespace std;
int main() {
	int a=20; 
	int *b;
	b=&a;
	cout<<b<<endl;
	return 0;//输出为地址值
}

#include<iostream>
using namespace std;
int main() {
	int a=20; 
	int *b;
	b=&a;
	cout<<*b<<endl;
	return 0;//输出20
}

由于定义了b是一个指针变量,其便具有了指针的功能;之后取地址符&变起到了将a的地址值赋给b的作用。
那么为什么前一段代码输出为地址值,后一段为int数据类型呢?这只因为:前一段代码,由于b已经是一个指针变量了,与前文一样,作为指针,输出的是地址;后一段代码,加上了星号,等于又强调了“b毕竟还是个变量”,因次输出为替换了新地址后该内存空间内存储数据的值。
特别强调:未先定义指针变量,无法使用“&”运算符;或者说,即使敲出了“&”并成功运行,那也并非为指针范围的运算。
由此便也体现出指针的作用之一:我不直接赋值,但我可以通过改变地址值来访问这个变量。
这就好比,虽然很多人没出生在北京,不能生下来就直接获得北京户口;但通过买了北京的房,取得了北京的住所(地址),获得了北京户口。
(此处只是一个比喻,本蒟蒻未曾有过北漂梦,也不是在北京上大学或工作,比喻如有不当还望谅解嘿嘿)
到此,指针的核心概念算是结束了。但如果仅仅如此,那指针岂不是很简单?所以接下来,难度加大~

2.3指针的指针

没错,前面说的是变量的指针,可指针本身也是有指针的。
指针的指针的定义格式如下:
数据类型 **指针的指针变量名;
确实,就是在定义好得出指针变量前再加上一个星号,那么指针的指针怎么用?我们通过下面一段代码便可以看出:

#include<iostream>
using namespace std;
int main() {
	int a=24; 
	int *b;
	b=&a;
	int **c;
	c=&b;
	cout<<**c<<endl;
	return 0;//输出为24
}

很明显,b取了a的地址,可c作为一个能对b“下手”的指针,又取了b的地址,输出了a的值。
这就好比:纽约原本是印第安人的地盘(a的地址),被荷兰人用水晶球骗到了(b取了a 的地址),最后又被美国人用24美元买到手(c取了b的地址)。于是乎,印第安小帐篷和荷兰人都不见了,取而代之的是繁(e)华(chou )的大都会。

2.4指针表达式

本部分内容主要是讲一些指针在写入表达式里的“骚操作”。来吧,翻过这座山~
(你会看到更多的山hhh)
前面我们已经掌握了*和&,这两个磨人的小妖精了,可运算符并不止他俩鸭~
先来看一个很正常的代码片段:

char ch='x';
char *cp=&ch;

这里很好理解,char类型的变量初始化赋值为“x”,指针变量cp取了它的地址
可如果是这么一个玩意儿呢?

*cp+1

是不是觉得很神奇?指针居然都还可以作加减?别慌,让我们冷静下来:
我们都知道,char类型字母+1,即代表字典序加一;而这里的*cp是一个指针变量,且取了地址,即这个地址存储的char类型数据字典序加一。
运行下面代码,果不其然:

```cpp
#include<iostream>
using namespace std;
int main() {
	char ch='a';
    char *cp=&ch;
    char ck=*cp+1;
    cout<<ck<<endl;
	return 0;//输出为b,即a的字典序加一
}

再来看一个例子:

#include<iostream>
using namespace std;
int main() {
	char ch='a';
    char *cp=&ch;
    char ck=*(cp+1);
    cout<<ck<<endl;
	return 0;//什么都没有输出
}

为什么会这样?因为这里的*(cp+1)访问的不再是变量值了,而是访问了之后的一个内存地址。可问题是,我们并不知道这后面地址是什么。这样,这个指针指向了一个未知域,即这是一个野指针
由此,我们可以看出,指针可做加减运算,也会有自己本身的物理意义。但这样的操作能否有效,还需视具体情况而定。对于这一类表达式,我们只用保持冷静,心中装着一件事:
弄清楚这里究竟是要描述一个变量值还是内存地址?
类似的,还有++*++cp,(*cp)++等诡异的式子,在此不作赘述。

总结

指针作为C/C++中基础部分比较难的部分,常令初学者痛苦不已。指针的学习首先需要对内存的概念有相对清晰的认识,然后紧抓“*”和“&”互为逆运算、“是变量or地址”这两个重要概念。
当然,指针的应用还有很多,具体地与函数、数组、结构体、数据结构的结合使用,我们以后再聊~
感谢阅读,希望对你有用:)

发布了15 篇原创文章 · 获赞 16 · 访问量 1092

猜你喜欢

转载自blog.csdn.net/weixin_44522586/article/details/103190801
今日推荐