C、C++为什么有指针这种数据类型?

C语言引入指针这个语法(C++保留了这一语法),肯定有其合理性和必要性的考量。虽然增加了语言的复杂性,但能更灵活地操作数据结构,也能直接操作内存。

1 首先要理解几个概念

1.1 存储程序的概念。数据要存得进去,取得出来,还要考虑空间的效率和时间的效率。

1.2 数据存储涉及到一个地址的概念,但如果将真正的地址呈现在你面前,类似于一个身份证号码的纯数字的东西,不方便记忆,也不够直观,所以在编程语言中弄出了变量、常量、字面量这些概念,都用一个有一定含义的标识符(如变量名)来表示,变量名与地址的映射由编译器或解释器配合操作系统来处理。这样数据由标识符而不是具体地址呈现出来也就让程序更易于编写、阅读和调试。由此,变量也就有了左值和右值的概念,左值对应变量的地址,赋值表达式的左值只能是变量;右值对应变量的具体的实际的值,相应的,在赋值表达式中可以用变量去引用实际值。

C/C++这样的语言比较接近早期抽象计算机数据的思维方式,指针其实就是我们抽象数据并且这个数据是聚合但是实际内存离散的胶合层产物。后来出的语言通过其他的方式来抽象数据表示,将指针这个概念隐藏了,显得友好了,但是其实他还在那。

1.3 复杂的程序必须涉及到复杂的数据结构,也就是一定要考虑批量的数据处理。那数据元素的关系需要考虑。而存储到内存中,其实内存空间的地址是存在线性关系的,但变量名去把这个线性关系给弄没了。

例如,一块内存连续存了10个数据,这10个数据在内存地址上肯定存在线性关系,你如果知道了第一个数据的变量名,如果才能通过线性关系存取其他9个变量的数据呢?

这其实就是数组的概念,数组下标就是对内存地址线性关系的映射。

在C、C++中,就引入了指针的概念来映射内存中的地址并表示这个地址的线性关系。

其它语言也通过其它的方式(如引用)来达成类似的操作

1.4 另外还有一个问题,如果你想在程序运行时操作内存,由操作系统提供一块内存后返回的只是一个地址,而通常普通变量只能存储一个具体值,要存储地址就需要用到专门的存储地址的变量,那就是指针变量。

2 指针的作用

1.1 间接访问

存储区的数据通常是通过变量(或常量)进行访问,有了指针,就多了一个访问的方式,变量访问通常称为直接访问,指针访问也就称为间接访问。

利用指针变量间接访问某一单元或一片连续的存储区(如数组、结体体、类对象),在特定情形下,有一定优势。

正确灵活地运用指针,可以提高程序代码的质量。因为其能像汇编语言一样处理内在地址,可以有效地表示和引用各种数据结构,如方便地使用数组和字符串,结构体结合自引用的指针构造链表等。

1.2 用作函数参数和函数返回值

函数调用时,函数参数会分配内存空间并赋值,如果参数是指针则赋的不是具体值,还是地址值,对指针的操作则是对指针指向的变量的操作。这就是值传递和指针传递的概念,可以通过指针传递来修改其它函数中定义的非全局数据。当然,如果你因为安全性的考虑,不想去修改其它函数中定义的非全局数据,可以在形参前冠一个const,作为常量的一个限定。

指针传递其实质还是在函数内部还是一个局部变量,但因为它是一个指针,它可以指向其它函数中数据,所以操作的对象因为指针的指向而发生了改变。

另外,函数指针用作函数参数时,可以由一个函数根据具体情况调用不同的函数。

另外,函数通常只能返回一个值,当然如果返回结构体和数组也可以返回多个值。有了指针,也可以通过返回数组指针或结构体指针来返回多个值

1. 3 灵活引用数组

如C语言中的字符串用字符数组来定义,两个字符数组不能直接赋值,但利用字符数组指针则可以。

另外,利用指针来操作数据在特定情形下有其方便性。

数组名就是指针,但是它是一个常量指针,对应数组第一个元素的地址,数组名可以直接赋值给指针。

1.4 动态分配内存

利用指针在程序运行时动态分配内存是指针最重要的一个功能。

我们先来考虑一个问题,如果你想定义一个数组来保存一个班级的姓名,那你定义这个数组是容纳多个个元素呢?如果这个元素数量在程序运行时再确定是一个最佳的方式。如果你声明一个普通数组,必须在运行前(编译时确定,其实是在定义数组时即具体确定)确定数组的大小,这是静态数组、静态绑定的概念。利用指针可以在运行时(编译完后、程序运行时由程序与用户交互或根据某个中间结果来视情况确定)再来确定这个数组的大小,具体的操作就是申请一块根据运行时的具体情况确定大小(某个类型的元素数量)的内存,返回一个内存地址,把这个地址赋给一个指针,利用这个指针来操作这个数组(对应的内存),这是动态数组、动态绑定的概念。通常动态内存分配是分配内存中堆的数据。

在C语言中,通过malloc()、free()等函数来申请内存并返回内存地址或释放内存。

在C++语言中,还可以通过new、delete两个运算符来申请内存并返回内存地址或释放内存。

-End-


分享到:


相關文章: