【C++ Lab】 对于解引用符*以及与运算符[]优先级的探索


我想很多人都看过运算符优先级表,但有时候对于一些情况可能会混淆,不过一个万能方法是——加括号改变/确保优先级。尽管"加括号"确实是个万能方法,但在有时间去摸索的时候还是尽可能弄清楚优先级为好,这样更有助于理解,甚至可以在摸索的过程中发现"新大陆",这也是做此次探索的目的。

【结论】

先把结论摆上吧:
【结论一】解引用符*不能"解空气",即被解引用的指针变量不能为野地址或NULL

【结论二】运算符[]的优先级高于解引用符*。
因此对于一个二级指针如int** a;,如果要用它来表示一个一维数组,则数组中元素表示为(*a)[i],其中的小括号不能少。

【验证过程】

阶段一 探究初步

#include<iostream>
#include<stdlib.h>

int main(){
	using namespace std;
	int ** a=NULL; //注意悬空,防止野指针 
	//cout<<"a="<<a<<endl;
	*a = (int*)malloc(sizeof(int)*3);
	for(int i=0;i<3;++i)
		(*a)[i] = i+1;
		
	for(int i=0;i<3;++i)
		cout<<(*a)[i]<<endl;
		
	return 0;
}

【运行结果】
在这里插入图片描述

阶段二 理解解引用符——*

以上为我一开始写的代码,但是一运行就发现main函数返回了一个很大的值(如上图),显然是出现了问题(即便我不把指针变量a悬空也是如此),其实原因很简单,我当时并没有给指针变量a本身提供一个"合法处所",即少了一句a=(int**)malloc(sizeof(int));,但这就使得二级指针a充当着二维数组了(我们是想要把二级指针a用于一维数组),因此我把代码改了改,如下代码块所示。

#include<iostream>
#include<stdlib.h>

int main(){
	using namespace std;
	int ** a=NULL; //注意悬空,防止野指针 
	int* arr=NULL;
	a = &arr;
	//cout<<"a="<<a<<endl;
	*a = (int*)malloc(sizeof(int)*3);
	for(int i=0;i<3;++i)
		(*a)[i] = i+1;
		
	for(int i=0;i<3;++i)
		cout<<(*a)[i]<<endl;
		
	return 0;
}

【运行结果】
在这里插入图片描述
可能有人会有疑问了,为何在不改变第一个代码块代码的前提下,仅仅添加了int* arr=NULL; a=&arr;后,就能正常运行了呢?关键在于a指针变量所指的地址是否存在。

我们要明白*a的意思是"对于a所指的地址解引用,并取其存储的值",对于一开始的int ** a=NULL; *a = (int*)malloc(sizeof(int)*3);,a是空指针,没有指向实际的地址,这时候*a即取虚空地址存储的值,相当于"取空气",这当然是非法的了,这种情况下就需要先给a本身申请一个存储空间,也就是对应着a=(int**)malloc(sizeof(int));,然后再进行后续的解引用等指令。

对于后面的代码块,这时候a=&arr;,尽管arr=NULL,但是它的地址是非空的,即&arr!=NULL,这时候赋予a的自然就是一个实实在在的"合法处所"了,因此*a——对于a的解引用就是"名正言顺"了。

到此我们可以得出【结论一】:解引用符*不能"解空气",即被解引用的指针变量不能为野地址或NULL

阶段三 步入正题——[]与*优先级探索

这一步其实很简单,我们只要把第二个代码块中(*a)[i]所加的小括号去掉就好,如果运行结果符合预期,那么就说明解引用符*的优先级高于运算符[];若运行出错,则说明解引用符* 的优先级低于运算符[]。

#include<iostream>
#include<stdlib.h>

int main(){
	using namespace std;
	int ** a=NULL; //注意悬空,防止野指针 
	int* arr=NULL;
	a = &arr;
	cout<<"The address of arr is "<<&arr<<endl;
	*a = (int*)malloc(sizeof(int)*3);
	for(int i=0;i<3;++i)
		*a[i] = i+1;
		
	for(int i=0;i<3;++i)
		cout<<*a[i]<<endl;
		
	return 0;
}

【运行结果】
在这里插入图片描述
去掉小括号运行就出错了,从而得到了我们的【结论二】:运算符[]的优先级高于解引用符*

所以有些时候,如果对于网上的答案持怀疑态度,那么不妨自己设计个简单实验试试,说不定你就找到了答案,并且这远比你去网上搜寻得到的解答印象深刻。

如果文章中有不妥之处,欢迎大家在评论区指点批评~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章