C语言非常道
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.2 什么是指针

简单地将一元&运算符的结果视为地址,是有问题的。地址相当于门牌号码,在有些人的眼里,它也许类似于一个整数。然而仅凭一个地址,我们是无法访问数据的。想想看,地址不能告诉你应该以什么类型来读取和解释那个变量的内容,是signed char,还是unsigned int?进一步地,因为没有类型信息,翻译软件在翻译程序时,也不知道那个地址上的变量有多大,应该读取或写入一个字节呢,还是四个字节?

所以,在C语言里,一元&运算符的结果(值)并不单纯是一个地址,而是一个包含了类型信息的地址。如果变量m的类型是int,则表达式& m的值不单包含了地址信息,还将包含这样的信息:这个地址用于访问一个int类型的变量。否则的话,表达式* & m = 2和++* & m不能正确执行,因为它不知道被指向的变量有多大,它的内容用什么类型来解释。

那么,如何描述这样的值呢?如图4-2所示,从表达式& m计算出一个值,这个值像指针一样,指向那个地址上的变量。鉴于这种类比特别形象,C语言引入了指针类型,简称指针,并规定一元&运算符的结果(值)是指针类型。

图4-2 指针的含义

在C语言里,整数类型是个统称,实际上包含了char、short和long int等具体的类型。同样地,指针类型也是个统称,根据它所指向的类型,可细分为指向char的指针、指向short的指针、指向long int的指针,等等。

一元&运算符称为取地址运算符,它需要一个右操作数,而且必须是左值或者函数指示符。这是很自然的,只有内存中的变量,或者函数才有地址,你不能取一个常量的地址,比如& 250,这很荒唐。另外需要注意,如果一个左值是一元&运算符的操作数,则不执行左值转换。

为方便起见,人们经常把指针类型的值也叫作“指针”。不过这不会引起混淆,通过具体的上下文大家都能明白所指。比如说,C语言规定,如果操作数的类型为T,则一元&运算符的结果是指向T的指针。在这里,“指针”就是“指针类型的值”。

在源文件c0401.c中,因为变量m的类型是int,所以一元&运算符的结果(也就是表达式& m的值)是指向int的指针。当然了,如果m的类型是char,则一元&运算符的结果是指向char的指针。

反过来,为了还原指针所指向的变量和函数,需要使用一元*运算符。C语言规定,一元*运算符的操作数必须是一个指针(类型的值)。如果操作数是指向某变量的指针,则一元*运算符的结果是个左值,代表那个变量;如果操作数是指向函数的指针,则一元*运算符的结果是函数指示符,代表那个函数;如果操作数的类型是指向T的指针,则一元*运算符的结果类型为T

因此,在上面的程序中,因为表达式& m的值是指向int的指针,故表达式* & m的结果是得到一个int类型的左值,代表指针所指向的变量(实际上是变量m)。