本帖最后由 09927306 于 2011-1-8 18:35 编辑
第6章:指针 【例6-1】 当变量或数组定义后,就可以用&运算符来查看它们的地址。
- main()
- { int a=1;
- float b=2;
- double c=3;
- int d[6];
- printf("address of a is %p\\n",&a);
- printf("address of b is %p\\n",&b);
- printf("address of c is %p\\n",&c);
- printf("address of array d is %p\\n",d);
- printf("address of d[0] is %p\\n",&d[0]);
- printf("address of d[1] is %p\\n",&d[1]);
- }
复制代码
在printf()函数中,用%p来控制地址量的输出,可以得到4位十六进制数表示的地址。也可以用%x控制输出地址量。它们的差别在于:%p输出的地址固定为4位,不足4位的补以前导0,而%x则不加前导0。程序运行结果如下(不同的机器配置,输出的地址值也不同,仅作参考):
address of a is FFC6
address of b is FFC8
address of c is FFCC
address of array d is FFD4
address of d[0] is FFD4
address of d[1] is FFD6
【例6-2】 使用指针访问变量示例。
- main()
- { int a,*p=&a;
- scanf("%d",p); /*等价于scanf("%d",p);*/
- (*p)++; /*等价于a++;*/
- printf("%d\\n",p[0]); /*等价于printf("%d\\n",a);*/
- }
复制代码
注意,在(*p)++中,由于“*”和“++”优先级相同,结合性均为从右到左,因此括号是必须的。若写成*p++就表示先取a的值,然后将p指向下一个数据单元,而下一个数据单元中的值是不确定的,从而造成输出结果为不定值。 【例6-3】 通过将指针加减一个整数来移动指针示例。
- #include <stdio.h>
- main()
- { int a=10,b=20,c=30,d=40;
- int *pb=&b;
- printf("%d,%d,%d,%d,%d\\n",*(pb-1),*pb,*(pb+1),*(pb+2));
- }
复制代码
程序运行时,int型指针pb中存放的是同类型变量b的地址FF02,即pb指向变量b。pb+1表示pb的值在FF02的基础上增加2(字节),结果为FF04,这是变量c的首地址,因此,*(pb+1)表示访问变量c的值。同样,*(pb–1)表示访问FF00即变量a的值,*(pb+2)表示访问FF06即变量d的值。程序运行结果如下:
10,20,30,40
【例6-4】 指针被赋值后,指针的指向发生变化的示例。
- #include <stdio.h>
- main()
- { int a=10,b=20;
- float x=2.5;
- int *p=&a;
- printf("%d",*p);
- p++;
- printf("%d",*p);
- p++;
- printf("%d\\n",*p);
- }
复制代码
程序运行时,在进行p++运算前,p指向变量a;在进行第一次p++运算后,p的值增加了2字节,结果指向了变量b;在进行了第二次p++运算后,p的值又增加了2字节,结果指向了变量x,而变量x占用4字节存储单元,所以,当用*p来访问时,将得到错误结果。编译系统并不具备纠正此类错误的能力,因此在移动指针时,一定要保证存储单元中数据类型的一致性。程序运行结果如下:
10
20
0
【例6-5】 两个同类型指针相减示例。
- #include <stdio.h>
- main()
- { float x[10];
- float *p,*q;
- p=&x[0];
- q=&x[5];
- printf("q-p=%d\\n",q-p);
- }
复制代码
指针p指向数组元素x[0],指针q指向数组元素x[5],其间相差5个数据单元,即5个元素,因此程序的运行结果如下:
q-p=5
【例6-6】 用指针及移动指针来实现一维数组的输入和输出。
- #include <stdio.h>
- main()
- { int a[10];
- int *p=a;
- for (;p<a+10;p++)
- scanf("%d",p);
- for (p=a;p<a+10;p++)
- printf("%d",*p);
- printf("\\n");
- }
复制代码
在该程序中,当定义了指向数组a的指针p后,在scanf()执行时,虽然每次循环的输入项都是p,但由于p的值随着p++在不断增加,即p的指向在不断向数组的底部移动,因此能把输入的数据依次保存到各个数组元素中。循环结束后,指针p已指到数组a最后一个元素的后面,因此在输出时,要将p重新移动到数组a的首地址上。 【例6-7】 用数组和指针模拟堆栈。 堆栈是一种先进后出或后进先出的数据结构。堆栈的特点是最先进栈的数据要到最后才能出栈。例如,若干列火车通过一条铁轨入库,最后入库的火车要最先出库。为了模拟堆栈,可以设置一个指向数组的指针,通过指针的移动可以很方便地模拟入栈和出栈。假设堆栈长度为N个整数,程序如下:
- #include <stdio.h>
- #define N 10
- main()
- { int a[N];
- int i,*p=a;
- while (p<a+N)
- scanf("%d",p++); /* PUSH(入栈) */
- while (p>a)
- printf("%d",*(--p)); /* POP(出栈) */
- printf("");
- }
复制代码
程序的第一个while循环模拟入栈操作,通过将指针逐步向数组的底部移动来顺序输入各个元素值;第二个while模拟出栈操作,通过将指针逐步向数组的顶部移动来反序输出各个元素值,运行情况如下:
1
2
3
4
5
6
7
8
9
10↙
10
9
8
7
6
5
4
3
2
1
【例6-8】 定义一个int型二维数组a[M][N],按存储结构定义数组指针p,利用指针按行的顺序输入数据,并按矩阵形式输出。其中,数组元素a[j]可以用*(&a[0][0]+i*N+j)、*(a[0]+i*N+j)、*(*a+i*N+j)、*(p+i*N+j)或p[i*N+j]等形式来访问。程序如下:
- #define M 5
- #define N 4
- main()
- { int a[M][N],*p=a[0],i,j;
- for (;p<a[0]+20;p++)
- scanf("%d",p);
- p=a[0];
- for(i=0;i<M;i++)
- { for(j=0;j<N;j++)
- printf("%d ",p[i*N+j]);
- printf("\\n");
- }
- }
复制代码
【例6-9】 用行指针和指针移动的方法求二维数组a[M][N]各行的平均值,并将各行平均值依次存放在数组b[M]中。程序如下:
- #define M 5
- #define N 4
- main()
- { static int a[M][N],(*pa)[N]=a,i,j;
- float b[M],*pb=b,s;
- for (i=0;i<M;i++)
- for (j=0;j<N;j++)
- scanf("%d",&pa[i][j]);
- for (i=0;i<M;i++)
- { s=0;
- for(j=0;j<N;j++)
- s+=pa[i][j];
- pb[i]=s/N;
- }
- for(i=0;i<M;i++)
- printf("%f",pb[i]);
- }
复制代码
【例6-10】 用指针数组和指针移动的方法求二维数组a[M][N]各行的最大值,并将各行最大值依次存放在数组b[M]中。
- #define M 5
- #define N 4
- main()
- { static int a[M][N],*pa[M]={a[0],a[1],a[2],a[3],a[4]},i,j;
- float b[M],*pb=b,s;
- for (i=0;i<M;i++)
- for (j=0;j<N;j++)
- scanf("%d",&pa[i][j]);
- for (i=0;i<M;i++)
- { s=pa[0][0];
- for(j=0;j<N;j++)
- if(s<pa[i][j]) s=pa[i][j];
- pb[i]=s;
- }
- for(i=0;i<M;i++)
- printf("%f",pb);
- }
复制代码
上一章:C语言案例教程 - 第五章 数组和字符串
下一章:C语言案例教程 - 第七章 程序的模块结构和C函数
|