在大一的课程C语言程序设计中,课本上对于指针这块的讲解太浅了,所以一直对指针的概念不明确,在看了《C++ Primer Plus》这本书关于指针的内容后,终于弄明白了指针这方面的知识,因此写篇博客再来总结一下。
首先要明确的是指针是也是一种数据类型,和我们所熟知的int,float,char等数据类型一样(不同的是后者是基本数据类型),在C语言中,指针的声明通常使用int *pt
这样形式,这也让我潜意识中把指针和int
以及“数值”联系在了一起,以致后来一直对指针的怎样表示的是地址,怎样表示的是数值不明白。但是实际上,指针是与基本数据类型不同的类型。
“ * ”称为解除引用运算符(当然也是乘法的运算法),编译器通过上下文来确定这个符号到底是解除引用运算符还是乘法运算符,因此在指针的声明中,空格并没有什么影响,以下三种表达方式是相同的:
int* pt;
int *pt;
int * pt;
指针主要用于存储地址,这与我们平时使用的声明方式所表达的相反,例如int a
,a表示的是数值,而地址为派生量;指针声明int* pt
,pt表示的是地址,而数值为派生量。至于指针声明前面的int,float,char
等基本数据类型,是告诉编译器我们将在pt这个地址上存储的是什么类型的值。如果我们直接输出pt,得到的是一个地址,利用解除引用运算符对其操作后再输出,得到的是地址上存储的值;如果我们直接输出a,得到的是a的值,而用引用符(&)对其操作后再输出,得到的是a的地址。我们看以下代码:
int a = 5; // 声明变量a=5
int* pt = &a; // 将a的地址存储到指针pt上
std::cout << pt << endl; // 输出a的地址
std::cout << *pt; // 输出a的值
而直接对指针进行整型赋值都是不合法的,即使对其赋值十六位表示的地址,如下:
int* pt2;
pt2 = 1; // 不合法
*pt2 = 1; // 合法但是十分不建议使用
pt2 = 0133FB0C; // 不合法
pt2 = (int*)0133FB0C; // 强制数据转换后赋值合法
对于*pt2 = 1
不建议使用的原因是:在声明一个未初始化的指针时,指针所存储的地址不一定是哪个位置的,也就是说未初始化的指针有可能存储程序内某个变量的地址。例如我们声明指针pt2但没有对其赋值,编译器可能将pt2指向了变量a的地址(即编译器将a的地址存储到了pt2中,因为在声明一个变量或指针时,如果我们没有对其初始化,那么编译器就会对其进行初始化,变量可能会被赋值为编译器的默认值或者任意一个值,而指针则会被随机指向一个地址),那么我们之后我们对*pt2
进行赋值后,a的值也随之改变,这就会导致程序一个十分难以察觉的bug。所以一定要在对指针应用解除引用运算符之前对其进行初始化。
如果我们想指针在声明时就有一个“安全”的地址值,也就是指针声明后指向的是一块没有被用过的地址,我们可以利用new
来创建,如int* pt = new int;
在C语言中也可以用malloc
函数,不过C++的new
更方便也更安全。
网友评论