9.1 关于地址和指针
要想搞清楚地址和指针的概念,首先要清楚变量在内存中的存储方式及变量是如何被存取的。
众所周知,程序中定义的某个变量,在编译时系统会给这个变量相应地分配与该变量类型相匹配的内存单元。即按照程序中所定义的变量类型,分配与该变量类型所占相同长度的空间。在内存区中每一个字节都有一个编号,这个编号就是“地址”,它相当于每个变量的房间号。变量的数据就存放在地址所标识的内存单元中,变量中的数据其实就相当于仓库中各个房间存放的货物。如果内存中没有对字节编号,系统将无法对内存进行管理。内存的存储空间是连续的,因此内存中的地址号也是连续的,并且用二进制数表示,为了直观起见,在这里将用十进制数进行描述。
真考链接
指针用于存放其他数据的地址。当指针指向变量时,利用指针可以引用该变量;当指针指向数组时,利用指针可以访问数组元素;当指针指向函数时,此时指针变量中存放函数的入口地址,可以通过指针调用该函数;当指针指向结构时,可以用指针引用结构变量的成员。
一般微机使用的C系统为整型变量分配2个字节,为实型变量分配4个字节,为字符型变量分配1个字节,为双精度类型变量分配8个字节。当某一变量被定义后,其内存中的地址也就确定了。例如:
int x,y;
float z;
这时,系统为x和y分配两个字节存储单元,为z分配了4个字节的存储单元,如图9.1所示,图中的数字只是表示字节的地址。每个变量的地址是指该变量所占存储单元的第一字节的地址。在这里,称x的地址为2012,y的地址为2015,z的地址为2201。
图9.1 x、y、z的存储单元分配
一般情况下,在程序中只需定义变量并指出变量名,无须去知道每个变量在内存中的具体地址,由C编译系统来完成每个变量与其具体地址发生联系的操作。在程序中对变量进行存取操作,实际上也就是对某个变量的地址存储单元进行操作。这种直接按变量的地址存取变量的方式称为“直接存取”方式。
在C语言中,还可以用另一种称为“间接存取”的方式来完成对变量进行存取的操作,即将变量的地址存放在另一种类型的变量中,从而通过这种新的变量类型来得到变量的值。按C语言规定,可以在程序中定义整型变量、实型变量、字符型变量等,也可以定义这样一种特殊的变量,它是专门用来存放地址的。假设定义了一个变量p,用来存放整型变量i的地址,它的地址被分配为1010字节,可以通过下面语句将i的地址(1500)存放到p变量中:
p=&i;
这时,p的值就是1500,即变量p是i所占用单元的起始地址。要存取变量i的值,也可以用间接的方式,先找到存放“i的地址”的变量p,从中取出i的地址(1500),然后到1500、1501字节取出i值。
由于通过地址能找到所需的变量单元,就可以说:地址“指向”该变量单元。所谓“指向”就是通过地址来体现。在C语言中,将地址形象地称为“指针”,意思是通过它能找到以它为地址的内存单元,这里包含有一个方向指向的意思。一个变量的地址称为变量的“指针”。一个专门用来存放另一个变量的地址的变量(即指针),则称它为“指针变量”。
小提示
变量的类型不同,其在内存中所占的空间也不一样。
常见问题
在程序中定义了一个变量名,编译时系统给这个变量开辟存储单元,如果要对这个变量进行操作,是否需要知道它在内存中的存储位置呢?
只要在程序中定义了变量并指出变量名,无须去知道每个变量在内存中的具体地址,因为 C编译系统来完成每个变量与其具体地址发生联系的操作。在程序中对变量进行存取操作,实际上也就是对某个变量的地址存储单元进行操作。