通常来说,指针是一个其数值为地址的变量(或更通常地说是一个数据对象)。
正如char类型的变量用字符做为其数值,而int类型变量的数值是整数,指针变量的数值表示的是地址。
若是您将某个指针变量命名为ptr,就可使用以下语句:
ptr=&pooh; /*把pooh的地址赋给ptr*/
对于这个语句,咱们称ptr指向pooh。ptr和&pooh的区别在于前者为一变量,然后者是一个常量。固然,ptr能够指向任何地方:
ptr=%bah; /*令ptr指向bah而不是pooh*/
这时,ptr的值是bah的地址。
要建立一个指针变量,首先须要声明其类型。假设您想把ptr声明为能够存放一个int数值的地址,就须要 使用下面介绍的新运算符。编程
9.7.1 间接运算符
假定ptr指向bah,以下所示:
ptr = &bah;
这时就能够使用间接(indirection)运算符*(也称做取值(dereferencing))来获取bah中存放的数值(不要把这种一元运算符和表示乘法的二元运算符*相混淆)。
val = *ptr; /*获得ptr指向的值*/
语句ptr=&bah;以及语句val=*ptr;放在一块儿等同于下面的语句:
val = bah;
由此看出,使用地址运算符和间接运算符能够间接完成上述语句的功能,这也正是“间接运算符”名称的由来。编程语言
9.7.2 指针声明
pointer ptr; /*不能这样声明一个指针*/
为何不能这样声明?由于这对于声明一个变量为指针是不够的,还须要说明指针所指向变量的类型。缘由是不一样的变量类型占用的存储空间大小不一样,而有些指针操做须要知道变量类型所占用的存储空间。同时,程序也须要了解地址中存储的是何种类型的数据。例如,long和float两种类型的数值可能使用相同大小的存储空间,可是它们的数据存储方式彻底不一样。指针的声明形式以下:
int *pi; /*pi是指向一个整数变量的指针*/
char *pc; /*pc是指向一个字符变量的指针*/
float *pf,*pg; /*pf和pg是指向浮点变量的指针*/
类型标识符代表了被指向变量的类型,而星号(*)表示该变量为一指针。声明int *pi; 的意思是pi是一个指针,并且*pi是int类型的。
*和指针之间的空格是可选的。
pc所指向的值(*pc)是char类型的。而pc自己又是什么类型呢?咱们把它描述为“指向char的指针”类型。pc的值是一个地址,在大多数系统内部,它由一个无符号整数表示。可是,这并不表示能够把指针看做是整数类型。一些处理整数的方法不能用来处理指针,反之亦然。例如,能够进行两个整数相乘,而指针则不能。所以,指针的确是一种新的数据类型,而不是整数类型。因此,正如前面提到的,ANSI C 专门为指针提供了%p输出格式 。函数
9.7.3 使用指针在函数间通讯spa
在程序清单9.15中,函数interchange()使用了指针参数,咱们将对该函数进行详细的讨论。指针
程序清单9.15 swap3.c程序code
#include <stdio.h> void interchange(int *u,int *v); int main(void) { int x = 5,y = 10; printf("Originally x = %d and y=%d.\n",x,y); interchange(&x,&y); /*向函数传送地址*/ printf("Now x = %d and y = %d.\n",x,y); return 0; } void interchange(int *u,int *v) { int temp; temp = *u; /*temp获得u指向的值*/ *u = *v; *v = temp; }
下面咱们分析程序清单9.15的运行状况,首先,函数调用语句以下:对象
interchange(&x,&y);ci
能够看出,函数传递的是x和y的地址而不是它们的值。这就意味着interchange()函数原型声明和定义中的形式参数u和v将使用地址做为它们的值。所以,它们应该声明为指针。因为x和y都是整数,因此u和v是指向整数的指针。其声明以下:原型
void interchange(int *u,int *v)io
接下来,函数体进行以下声明:
int temp;
从而提供了所需的临时变量。为了把x的值存储在temp中,须要使用如下语句:
temp = *u;
注意,由于u的值是&x,因此u指向x的地址。这就意味着*u表明了x的值,而这正是咱们须要的数值。不要写成以下这样:
temp = u; /*这样作不行*/
上面的语句中,由于赋给变量temp的只是x的地址而不是x的值,因此不能实现数值的交换。
一样,把y的值赋给x,须要使用下面的语句:
*u = *v;
其执行结果至关于:
x = y;
在示例程序中,咱们用一个函数实现了x和y的数值交换。首先,函数使用xy的地址做为参数,这使它能够访问xy变量。经过使用指针和运算符*,函数能够得到相应存储地址的数据,从而就能够改变这些数据。
一般状况下,能够把关于变量的两类信息传递给一个函数。若是函数的调用形式以下:
funcation (x);
这是传递的是x的值。可是若是使用下面这种函数调用形式:
funcation (&x);
那么会把x的地址传递给函数。第一种调用形式要求函数定义部分必须包含一个和x具备相同数据类型的形式参数。以下所示:
int function (int num);
而第二种形式要求函数定义部分的形式参数必须是指向相应数据类型的指针:
int funcation (int *ptr);
使用函数进行数据计算等操做时,可使用第一种形式。可是,若是须要改变调用函数中的多个变量的值时,就须要使用第二种形式。其实,使用scanf()时已经使用了第二种形式。例如,当须要为变量num读取一个数值时,能够调用函数scanf("%d",&num);该函数调用的意思是先读取一个数值,而后将其存储到经过参数得到的地址中。
尽管interchange()只使用局部变量,可是经过使用指针,该 函数能够操做main()中变量的值。
***************************************************
关于变量:变量名称、地址和数值
前面关于指针的讨论中,变量名称、地址以及数值之间的关系是其关键所在。
编写程序时,一个变量通常有两种属性:变量名和数值(固然,还有其余属性,如数据类型等,但它们与这个主题无关)。程序被编译和加载后,同一个变量在计算机中的两个属性是地址和数值。变量的地址能够被看做是在计算机中变量的名称。
在许多编程语言中,变量地址只由计算机处理,对于编程人员来说彻底不可见。可是在C中,可使用运算符&对变量的地址进行操做。
&barn就表示变量barn的地址。
能够经过使用变量名得到变量的数值。
例如printf("%d\n",barn)输出的是barn的数值。
固然 ,也可使用运算符*从地址中获取相应的数值。
对于语句pbarn = &barn;,*pbarn是存储在地址&barn中的数值。
总之,普通的变量把它的数值做为基本数值量,而经过使用运算符&将它的地址做为间接数值量。可是对于指针 来说,地址是它的基本数值量,使用运算符*后,该地址中存储的数值是它的间接数值量。