第6章 指针
- 格式:doc
- 大小:85.50 KB
- 文档页数:7
第6章 指针与数组
2.1 指针
指针是C语言的强大功能之一。前面我们讨论过,变量就是一个存储位置,它是我们引用一个存储位置的名字。同时,每个存储位置都有一个编号,这个编号就是存储位置的地址。地址给PC硬件提供了引用具体数据项的手段。指针是一种类型的变量,称为指针变量,该变量是用来存储其他变量(存储位置)的地址的。
我们可以使用指针符号处理数组中存储的数据,相应的执行速度往往比使用数组符号要快。另外,在定义自己的函数时,指针将被广泛使用,以便能够在函数内部访问在函数外部定义的大块数据——比如数组。
2.1.1 取址运算符
变量就是一个存储位置,那么如何获得该变量(该存储位置)的地址呢?可以通过地址运算符&获得变量的地址。其一般格式为:
&变量名
实例2-1:获取变量的地址
问题描述:编写程序,返回for循环循环控制变量的地址及一个长整型、一个整型变量的地址。
#include
int main()
{
for(int i=0;i<3;i++)
printf("变量i的值: %d 变量i的地址:%x\n",i,&i);
long var1=99;
int var2=68;
printf("变量var1的值:%d 变量var1的地址:%x\n",var1,&var1);
printf("变量var2的值:%d 变量var2的地址:%x\n",var2,&var2);
return 0; // indicates successful termination
}
变量i的值: 0 变量i的地址:12fed4 变量i的值: 1 变量i的地址:12fed4
变量i的值: 2 变量i的地址:12fed4
变量var1的值:99 变量var1的地址:12fec8
变量var2的值:68 变量var2的地址:12febc
代码分析与讨论:
1)地址运算符&。地址运算符&是一个一元运算符,返回操作数的地址。例如:
long var1=99;
printf("变量var1的值:%d 变量var1的地址:%x\n",var1,&var1);
&var1为变量var1的地址。
2)自动变量的地址是由高地址到低地址。观察变量的地址,它们是依递减的。自动变量在堆栈中,按照声明的顺序,从由高地址到低地址。
2.1.2 指针的声明和初始化
指针变量存储特定类型的另一个变量的地址。就像任何其它变量一样,指针变量也有名称,另外指针还有类型,以指出指针变量值所标识的存储位置所存放值的数据类型。如果某个指针变量值所标识的存储位置存放的是int类型数值,则该指针变量的类型是“指向int类型的指针”。在声明指针变量时,除了在名称前面用星号表明是指针变量之外,指针的声明与普通变量类似。其一般格式为:
类型 * 指针变量名称;
和其他变量一样,指针在使用前必须被声明。例如:
int number=98;
int* numberPtr, count;
声明了变量是numberPtr是int类型(即一个指向int值的指针),读做“numberPtr是一个指向int类型的指针”。同时,该声明指出变量count是一个int类型的变量。
语句:
numberPtr=& number;
将变量number的地址赋给指针变量numberPtr。该操作结果如图2-1所示。
图2-1 给指针赋值
&number
number
1008 numberPtr
1008 98 地址:1008 指针可以在声明或在赋值语句中初始化。指针可以被初始化为0、NULL或地址。值为0或NULL的指针不指向任何对象,称为空指针。NULL符号常量在头文件(和其他一些标准头文件)中定义,表示数值0。把一个指针初始化为NULL和0是等价的,但是C中约定使用0。只有整数0可以直接赋值给一个一个指针变量,而其他整数不能够直接赋值给一个一个指针变量。
2.1.3 指针的使用
指针的重要用途是存取指针所指变量中的数据值。这需要使用间接运算符*。将间接运算符*与某个指针一起使用时,就可以存取该指针指向变量的内容。其一般格式为:
*指针变量的名称
间接运算符又名解除引用运算符,它返回其指针操作数所指向变量的同义词(即别名)。而存取指针所指的变量中数据的过程被称为解除对指针的引用。
该运算符可能使人混淆的一个方面是相同的符号*现在有多种用途。星号是乘法运算符,还是间接运算,还是用于指针的声明。每次使用*时,编译器都能根据上下文区分其意义。当我们使两个变量相乘时——比如a*b,该表达式除了是乘法操作外,没有任何其他有意义的解释。
实例2-2:使用指针
问题描述:编写程序,使一指针初始化为NULL。然后使该指针引用一个变量,通过使用指针修改该变量的值。接着使指针引用另一个变量,并使用指针引用这个变量的值。
#include
int main()
{
long number1=26,number2=10;
long* numberPtr=NULL;
numberPtr=&number1;
*numberPtr=*numberPtr+12;
printf("\n");
printf(" number1=%d",number1);
printf(" &number1=%x",&number1);
printf("\n");
printf("*numberPtr=%d",*numberPtr);
printf(" numberPtr=%x",numberPtr);
numberPtr=&number2;
number1=*numberPtr*number1;
printf("\n");
printf("number1=%d",number1);
printf(" numberPtr=%x",numberPtr); printf(" *numberPtr=%d",*numberPtr);
printf("\n");
printf("&*numberPtr=%x",&*numberPtr);
printf(" *&numberPtr=%x", *&numberPtr);
printf("\n");
return 0;
}
number1=38 &number1=0012FED4
*numberPtr=38 numberPtr=0012FED4
number1=380 numberPtr=0012FEC8 *numberPtr=10
&*numberPtr=0012FEC8 *&numberPtr=0012FEC8
代码分析与讨论:
1)指针的声明和初始化。以下语句声明一个long类型的指针变量numberPtr,并将该指针变量初始化为NULL。这样确保该指针不包含任何有效的地址(即空指针)。
long* numberPtr=NULL;
它表示numberPtr是指向long值的指针(指针和指针变量是同义语)。每一个声明为指针的变量在其前面必须有一个*号,至于*离类型近还是离指针变量名近,编译器不会介意,这两种书写方式,结果相同。声明中出现的*不是一个运算符,它只表示被声明的变量是一个指针。
2)将指针指向一个变量。以下语句将变量number1的地址赋给指针变量numberPtr,这样numberPtr指针指向number1变量。
numberPtr=&number1;
记住,当用另一个变量的地址给指针变量赋值时,必须在该语句之前已经声明过该变量。另外,指针变量中只能够存放地址。
3)存取指针所指向变量的值。要存取指针变量所指变量的值,可在指针变量前加间接运算符*,它可表示指针所指的变量,以这种方式使用*,称为间接引用一个指针。在本例中,以上语句执行后,指针numberPtr指向变量number1,因此以下语句中*numberPtr是number1的别名,*numberPtr与number1是一样的,它们是同一个存储位置。
*numberPtr=*numberPtr+12;
它首先读取指针numberPtr所指变量的值26,然后将26加12,再将其和赋给指针numberPtr所指的变量。最后*numberPtr的值为38,也就是number1的值为38。
注意,变量可以出现的地方就可以使用间接引用一个指针。比如间接引用一个指针可以出现在赋值语句的左边,也可以出现在赋值语句的右边。也可以出现在表达式中。 声明指针变量后,若未指定指针变量的地址值,却间接引用一个指针,可能会导致致命的运行时错误,或者意外修改了重要数据,以致程序运行结束后可能得到错误结果。
4)可以改变指针的引用。指针引用一个变量后,可以修改指针的引用,使其指向另一个变量。以下语句使指针numberPtr指向另一个变量number2。
numberPtr=&number2;
这样*numberPtr和number2是同一个存储位置。numberPtr和number1就没有任何关系了。
number1=*numberPtr*number1;
它首先读取numberPtr指针指向的变量number2的值10,然后读取变量number1的值38,再将它们的乘积380赋给变量number1,最后变量number1的值为380。
注意:一个指针变量只能够指向同一个类型的变量。例如,numberPtr不能忽而指向一个long类型的变量,忽而指向一个double类型的变量。因此必须规定指针变量所指变量的类型。本例中,numberPtr只能够指向long类型的变量。换句话说,只有类型与指针变量类型相同的变量的地址才能够放到该指针变量中。
指向同一数据类型的不同指针,可以指向同一个变量。
5)&和*运算符互为反运算。&和*运算符互为反运算,以任意顺序把他们两个连续应用到numberPtr,它们“彼此抵消”,打印出相同的结果(numberPtr中的值)。
注意,间接引用一个非指针会导致编译错误。如*number1是错误的。但*&number1是正确的,*&number1与number1是等价的,这是因为先进行&number1运算,得number1的地址,再进行*运算,即&number1所指向的变量number1。
实例2-3:数的排序
问题描述:编写程序,输入两个数,并使其从大到小输出。
main()
{ int *p1,*p2,*p,a,b;
scanf("%d,%d",&a,&b);
p1=&a; p2=&b; if(a
{ p=p1; p1=p2; p2=p;}
printf("a=%d,b=%d\n",a,b);
printf("max=%d,min=%d\n",*p1,*p2);