在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。可见,一个指针变量的值就是某个内存单元的地址或称为某内存单元的地址。
1.变量的指针和指向变量的指针变量
变量的指针就是变量的地址。存放变量地址的变量就是指针变量。在C语言中,允许用一个变量来存放指针,这个变量就是指针变量。因此,一个指针变量的值就是某个变量的地址或称为某变量的指针。
1.1 指针变量的定义
一般形式为:类型说明符 * 变量名;
其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示该指针变量所指向的变量的数据类型。如int * p1;表示p1是一个指针变量,它的值是某个整型变量的地址。或者说p1指向一个整型变量。
对指针变量的定义包括3个内容:(1)指针类型说明,即定义变量为一个指针变量 (2)指针变量名 (3)变量值(指针)所指向的变量的数据类型。
1.2 指针变量的引用
指针变量同普通变量一样,使用之前不仅要定义声明,而且必须赋予具体的值。未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。指针变量的赋值只能是地址,绝不能是任何其他数据。
两个有用的运算符:
(1)&:取地址运算符
(2)*:指针运算符(或称“间接访问”运算符)
C语言中提供了地址运算符“&”来表示变量的地址。其一般形式为:&变量名;
设有指向整型变量的指针变量p,如要把整型变量a的地址赋予p可以有以下两种方法:
A>指针变量初始化方法 int a;int * p=&a;
B>赋值语句的方法 int a;int * p;p=&a;
定义两个整型变量i,x,还定义了一个指向整形值的指针变量ip。i,x中可存放整数,而ip中只能存放整形变量的地址。我们可以把i的地址赋予ip。ip=&i; 此时指针变量ip指向整型变量i,假设变量i的地址为1800.因此可以通过指针变量ip间接访问变量i,如:x=*ip;运算符“*”访问以ip为地址的存储区域,而ip中存放的是变量i的地址,可见,*ip访问的地址是1800的存储区域(因为是整数,实际上是从1800开始的2字节),它就是i所占用的存储区域,所以以上的赋值表达是等价于x=i;
例1:输入a和b两个整数,俺从大到小的顺序输出a和b。
#include<stdio.h>
#define SQ(y) (y*y)
main(){
int *p1,*p2,*p,a,b;
printf("please input two number:/n");
scanf("%d%d",&a,&b);
p1=&a;
p2=&b;
if(a<b){
p=p1;
p1=p2;
p2=p;
}
printf("/na=%d,b=%d/n",a,b);
printf("max=%d,min=%d/n",*p1,*p2);
}
1.3 指针变量作为函数的参数
指针类型可以作为函数的参数,它的作用是讲一个变量的地址传送到另一个函数中。
例2:题目同例1.用函数处理,而且指针类型的数据做函数的参数。
#include<stdio.h>
void swap(int *p1,int *p2){//交换变量a和b的值,其形参p1,p2为指针变量
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
main(){
int *p1,*p2,a,b;
printf("please input two number:/n");
scanf("%d%d",&a,&b);
p1=&a;
p2=&b;
if(a<b)
swap(p1,p2);//而非swap(*p1,*p2);
printf("/na=%d,b=%d/n",a,b);
}
例3:不能企图通过改变指针形参值的方法而改变指针实参的值。
#include<stdio.h>
void swap(int *p1,int *p2){//交换变量a和b的值
int *temp;
temp=p1;
p1=p2;
p2=temp;
}
main(){
int *point1,*point2,a,b;
printf("please input two number:/n");
scanf("%d%d",&a,&b);
point1=&a;
point2=&b;
if(a<b)
swap(point1,point2);
printf("/na=%d,b=%d/n",a,b);
}
其问题在于,实参指针point1将它指向的变量a的地址传给了形参p1,实参指针point2将它指向的变量a的地址传给了形参p2。而在子函数中,p1和p2的指向发生了改变,但它并没有改变point1和point2指向变量的值,所以*point1和*point2代表的还是a和b的值。
1.4 对指针变量的进一步说明
指针变量只能进行赋值运算、部分算术运算及关系运算。
A>>指针运算符
(1)取地址运算符&:取地址运算符“&”是单目运算符,其结合性为右结合,其功能是去变量的地址。
(2)取内容运算符*:取内容运算符“*”是单目运算符,其结合性为右结合,用来表示指针变量所指的变量。跟在“*”运算符之后的变量必须是指针变量。
指针运算符“*”和指针变量说明中的指针说明符“*”不是一回事。在指针变量说明中,“*”是类型说明符,表示其后的变量类型是指针类型。而表达式中出现的“*”则是一个运算符用于表示指针变量所指的变量。
B>>指针变量的运算
(1)赋值运算
1>指针变量初始化赋值,就是在定义指针变量的同时为它赋值。
2>把一个变量的地址赋予指向其数据类型的指针变量。如:int a,*pa;pa=&a;/*把整型变量a的地址赋予整形指针变量pa*/
3>把一个指针变量的值赋予指向相同类型变量的另一个指针变量。如:int a,*pa=&a,*pb;pa=pb;/*把a的地址赋予指针变量pb*/
4>把数组的首地址赋予指向数组的指针变量。如:
int a[5],*pa;pa=a;/*数组名表示数组的首地址,故可将其赋予指向数组的指针变量pa*/
也可写为:pa=&a[0];/*数组第一个元素的地址也是整个数组的首地址,也可将其赋值pa*/,也可使用初始化赋值方法:int a[5],*pa=a;
5>把字符串的首地址赋予指向字符类型的指针变量。如:char *pc;pa="C Language";或使用初始化复制的方法写为:char *pc="C Language"。并不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量。
6>把函数的入口地址赋予指向函数的指针变量。如:int (*pf)();pf=f;/*f为函数名*/
(2)加减运算
对于指向数组的指针变量,可以加上或减去一个整数n。
设pa是指向数组a的指针变量,则pa+n,pa-n,pa++,++pa,pa--,--pa都是合法的。
指针变量加上或减去一个整数n的意义是把指针指向的当前位置(指向某个数组元素)向前或向后移动n个位置。应注意,数组指针变量向前或向后移动一个位置和地址加1或减1在概念上是不同的。因为数组可以有不同的类型,各种类型的数组元素所占的字节长度是不同的。如指针变量加1,即向后移动1个位置表示指针变量指向下一个数据元素的首地址。而不是在源地址基础上加1。如:
int a[5],*pa; pa=a;/*pa指向数组a,即指向a[0]*/ pa=pa+2;/*pa指向a[2],即pa的的值为&a[2]*/
指针变量的加减运算只能对数组指针变量进行,对指向其他类型变量的指针变量进行加减运算是毫无意义的。
(3)两个指针变量之间的运算。
只有指向同一数组的两个指针变量之间才能进行此运算,否则毫无意义。
1>两指针变量相减。两指针变量的差是两个指针变量所指数组元素之间相差的元素个数,实际上是两个指针值(地址)的差再除以该数组元素的长度(字节数)。
2>两指针变量进行关系运算:指向同一数组的两指针变量进行关系运算克表示他们所指数组元素之间的关系。如:
pf1==pf2表示pf1和pf2指向同一数组元素。
pf1>pf2表示pf1处于高位置地址。
pf1<pf2表示pf1处于低位置地址。
指针变量还可以与0进行比较。设p为指针变量,则p==0表示p为空指针,它不指向任何变量。p!=0表示p不是空指针。
空指针是通过对指针变量赋值0值而得到的。对指针变量赋0值和不赋值是不同的。指针变量未赋值时,可以是任意值,是不能使用的。否则产生意外错误。而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已。
2. 指针数组和指向数组的指针变量
一个变量有一个地址,一个数组包含若干个元素,每个数组元素都在内存中占用存储单元,他们都有相应的地址。数组的指针是指数组的起始地址,数组元素的指针是数组元素的首地址。
2.1 指向数组元素的指针
一个数组是由连续的一块内存单元组成的。数组名就是这块连续内存单元的首地址。一个数组也是由各个数组元素(下表变量)组成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址。
2.2 通过指针引用数据元素
C语言规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素。
如果p的初值为&a[0],则:
(1)p+i和a+i就是a[i]的地址,或者说他们指向a数组的第i个元素。*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i]。
(2)指向数组的指针变量也可以带下标,如p[i]和*(p+i)等价。
2.3 数组名作为函数的参数
例4:将数组a中的n个整数反序存放。
#include<stdio.h>
#define N 10
void reverse(int *p,int n);
main(){
int i;
int a[N]={0,1,2,3,4,5,6,7,8,9};
printf("output orginal array:/n");
for(i=0;i<N;i++)
printf("%d ",a[i]);
printf("/n");
reverse(a,N);
printf("output changed array:/n");
for(i=0;i<N;i++)
printf("%d ",a[i]);
printf("/n");
}
void reverse(int *p,int n){
int m=(n-1)/2,temp;
int *head,*tail,*middle;
head=p,tail=head+n-1,middle=p+m;
for(;head<middle;head++,tail--){
temp=*head;
*head=*tail;
*tail=temp;
}
}
例5:从10个数中找到其中的最大值和最小值。
#include<stdio.h>
#define N 10
int max=0,min=0;//全局变量
void max_min(int array[],int n);
main(){
int i;
int a[N];
printf("please input ten number:/n");
for(i=0;i<N;i++)
scanf("%d",&a[i]);
max_min(a,N);
printf("max=%d,min=%d/n",max,min);
}
void max_min(int array[],int n){
int *array_end=array+n,*p;
//int min,max;//因为定义了局部变量,在该函数中覆盖全局变量,故出现错误
max=*array,min=*array;//相当于*(&array[0])
for(p=array;p<array_end;p++){
if(max<*p)
max=*p;
else if(min>*p)
min=*p;
}
return;
}
实参不用数组名,而用指针变量传递地址:
#include<stdio.h>
#define N 10
int max=0,min=0;
void max_min(int *array,int n);
main(){
int i;
int a[N];
printf("please input ten number:/n");
for(i=0;i<N;i++)
scanf("%d",&a[i]);
max_min(a,N);
printf("max=%d,min=%d/n",max,min);
}
void max_min(int *array,int n){
int *array_end=array+n,*p;
//int min,max;//因为定义了局部变量,在该函数中覆盖全局变量,故出现错误
max=*array,min=*array;
for(p=array;p<array_end;p++){
if(max<*p)
max=*p;
else if(min>*p)
min=*p;
}
return;
}
2.4 指向多维数组的指针和指针变量
A>指向多维数组的指针变量
把二维数组a[3][4]分解为一维数组a[0]、a[1]、a[2]之后,设p为指向二维数组的指针变量,可定义为:int(*p)[4]。
它表示p是一个指针变量,它指向包含4个元素的一维数组。若指向第一个一维数组a[0],其值等于a,a[0],或&a[0][0]等。
二维数组指针变量说明的一般形式为:类型说明符(*指针变量名)[长度]
其中“类型说明符”是所指数组的数据类型。“*”表示其后的变量是指针类型的变量,“长度”表示二维数组分解为多个一维数组时,一位数组的长度,也就是二维数组的列数。应注意,“*指针变量名”两边的括号不可少,如缺少括号则表示是指针数组。
例6:指向多维数组的指针变量举例
#include<stdio.h>
main(){
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int (*p)[4];
int i,j;
p=a;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
printf("%2d ",*(*(p+i)+j));
printf("/n");
}
}
3. 字符串指针和指向字符串的指针变量
3.1 字符串的表示形式
(1)用字符数组存放一个字符串,然后输出该字符串。
(2)用字符串指针指向一个字符串。
字符串指针变量的定义说明和指向字符变量的指针变量的定义说明的方法相同,只能按对指针变量的赋值不同来区别。对指向字符变量的指针变量应赋予该字符变量的地址。
如:char c,*p=&c;表示p是一个指向字符变量c的指针变量。
而char *s="C Language";则表示s是一个指向字符串的指针变量。把字符串的首地址赋予s。
例7:把字符串指针作为函数参数的使用举例。要求把一个字符串的内容复制到另一个字符串中,并且不能使用strcpy函数。函数cprstr的形参为两个字符指针变量。pss指向源字符串,pds指向目标字符串。注意表达式(*pds=*pss)!='/0'的用法。
#include<stdio.h>
cprstr(char * pds,char * pss){
while((*pss=*pds)!='/0'){
/*1>把pds指向的源字符串复制到pss所指向的目标字符串中,2>判断所复制的字符串是否为'/0',
若是,则表明源字符串结束,不再循环。否则pss和pds都加1,指向下一个字符。
*/
pss++;
pds++;
}
}
/*以下两种情况均可
cprstr(char * pds,char * pss){
while((*pdss++=*pds++)!='/0');
}
cprstr(char * pds,char * pss){
while(*pdss++=*pds++);
}
*/
main(){
char *pa="CHINA",b[10],*pb;
pb=b;
cprstr(pa,pb);
printf("string a=%s/nstring b=%s/n",pa,pb);
}
3.2 字符串指针变量与字符串数组的区别
使用字符数组和字符串指针变量都可实现字符串的存储和运算。但是两者是有区别的。
(1)字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符数组本身是存放在以该首地址为首的一块连续的内存空间中,并以'/0'作为串的结束标志。字符数组是由若干个数组元素组成的,它可用来存储整个字符串。
(2)对于字符串指针 char *ps="C Language";可以写为:char *ps; ps="C Language";而对于数组:static char str[]={"C Language"};不能写成char st[20];st=[]={"C Language"};
4. 函数指针变量
在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针向量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量成为“函数指针变量”。
4.1 函数指针变量的定义
函数指针变量定义的一般格式为:类型说明符(*指针变量名)();
其中“类型说明符”表示被指函数的返回值类型。“(*指针变量名)”表示“*”后面的变量是指针变量。最后的空括号说明指针变量所指的是一个函数。如:int (*pf)();表示pf是一个指向函数入口地址的指针变量,该函数的返回值(函数值)类型是整形。
例8:利用指针形式实现函数调用的方法。
#include<stdio.h>
int max(int a,int b){
if(a>b)
return a;
else
return b;
}
main(){
int max(int a,int b);
int (*pmax)();
int x,y,z;
pmax=max;
printf("input two numbers:/n");
scanf("%d%d",&x,&y);
z=(*pmax)(x,y);
printf("maximum=%d/n",z);
}
从上面程序中可以看出,采用函数指针变量形式调用函数的步骤如下:
(1)先定义函数指针变量。如main函数中“int (*pmax)();”,定义pmax为函数指针变量。
(2)把被调函数的入口地址(函数名)赋予该函数指针变量,如“pmax=max;”。
(3)用函数指针变量形式调用函数,如“z=(*pmax)(x,y);”。
(4)调用函数的一般形式为:(*指针变量名)(实参表);
注意函数调用中“:(*指针变量名)”的两边的括号不可少。
4.2 指针型函数
在C语言中允许一个函数的返回值是一个指针(即地址),这种返回指针值的函数成为指针型函数。
定义指针型函数的一般形式为:
类型说明符 * 函数名(参数表){函数体}
其中函数名之前加“*”号表明这是一个指针型函数,即返回值是一个指针。类型说明符表示返回的指针值所指向的数据类型。
例9:通过指针函数,并输入一个1~7之间的整数,并输出对应的星期名。
#include<stdio.h>
char * day_name(int n){
static * name[]={"Illegal","Monday","Tuesday","Wednesday",
"Thursday","Friday","Saturday","Sunday"};
return((n<1 || n>7)?name[0]:name[n]);
}
main(){
int i;
char * day_name(int n);
printf("please input a Day No:/n");
scanf("%d",&i);
if(i<0)
exit(1);
printf("Day No:%2d-->%s/n",i,day_name(i));
}
应注意函数指针变量和指针函数两者在写法和意义上的区别。如int(*p)()和int*p()是两个完全不同的量。int(*p)()是一个变量说明,说明p是一个指向入口函数地址的指针变量,该函数的返回值是整型量,(*p)两边的括号不能少。int *p()则不是变量说明而是函数说明,说明p是一个指针类型函数,其返回值是一个指向整型量的指针,*p两边没括号。作为函数说明,在括号内最好写入形式参数,这样便于与变量说明进行区分。
5. 指针数组和指向指针的指针
5.1 指针数组的概念
如果一个数组元素的值为指针时则称其为指针数组。指针数组是一组有序指针的集合。指针数组的所有元素都必须具有相同存储类型且指向相同数据类型的指针变量。
指针数组说明的一般形式为:类型说明符*数组名[数组长度] 其中类型说明符为指针值所指向的变量的类型。
如:int * pa[3];表示pa是一个指针数组,它包含3个数组元素,每个元素值都是一个指针,指向整型变量。
例10:通常可用一个指针数组来指向一个二维数组。指针数组中每个元素被赋予二维数组每一行的首地址,因此可理解为指向一个一维数组。
#include<stdio.h>
main(){
int a[3][3]={1,2,3,4,5,6,7,8,9},*pa[3],*p=&a[0],i;
for(i=0;i<3;i++)
pa[i]=a[i];
for(i=0;i<3;i++)
printf("%d,%d,%d/n",a[i][2-i],*a[i],*(*(a+i)+i));
printf("OK/n");
for(i=0;i<3;i++)
printf("%d,%d,%d/n",*pa[i],p[i],*(p+i));
}
应注意指针数组和二维数组指针变量的区别。二维数组指针变量是单个的变量,其一般形式为“*指针变量名”两边的括号不可少。而指针数组类型表示的是多个指针(一组有序指针)在一般形式中“*指针数组名”两边不能有括号。
如:int (*p)[3]表示一个指向二维数组的指针变量,该二维数组的列数为3或分解为一位数组的长度为3.
int *p[3]表示p是一个指针数组,有3个下标变量,p[0],p[1],p[2]均为指针变量。
例11:指针数组作为指针型函数的参数。
#include<stdio.h>
char * day_name(char * name[],int n){
char *pp1,*pp2;
pp1=*name;//输出错误提示
pp2=*(name+n);//输出正确输入下的字符串
return((n<1 || n>7)?pp1:pp2);
}
main(){
int i,*ps;
static * name[]={"Illegal","Monday","Tuesday","Wednesday",
"Thursday","Friday","Saturday","Sunday"};//指针数组,其每个元素都指向一个字符串
printf("please input a Day No:/n");
scanf("%d",&i);
if(i<0)
exit(1);
ps=day_name(name,i);
printf("Day No:%2d-->%s/n",i,ps);
}
例12:输入5个国家名并按字母顺序排列后输出。
#include<stdio.h>
void sort(int * name[],int n){
int i,j;
int *pt;
for(i=0;i<n;i++){
for(j=i+1;j<n;j++)
if(strcmp(name[i],name[j])>0){
pt=name[i];
name[i]=name[j];
name[j]=pt;
}
}
}
void print(int * name[],int n){
int i;
for(i=0;i<n;i++)
printf("%s ",name[i]);
printf("/n");
}
main(){
char *p;
static char * name[]={"CHINA","AMERICA","AUSTRALIA","FRANCE","GERMAN"};//指针数组
printf("the array before change:/n");
print(name,5);
sort(name,5);
printf("the array after change:/n");
print(name,5);
}
5.2 指向指针的指针
如果一个指针变量中存放的是另一个指针变量的地址,则成这个变量为指向指针的指针变量。
定义指向指针型数据的指针变量的格式如下:char **p;
p前面有两个*号,相当于*(*p),显然*p是指针变量的定义形式,如果没有最前面的*,那就是定义了一个指向字符数据的指针变量。现在它前面又有一个*号,表示指针变量p指向一个字符指针型变量。*p就是p所指向的另一个指针变量。
例13:使用指向指针的指针举例。
#include<stdio.h>
main(){
char * name[]={"Follow me","BASIC","Great Wall","FORTRAN","Computer design"};
char **p;//指向指针的指针变量
int i;
for(i=0;i<5;i++){
p=name+i;
printf("%s/n",*p);
}
}
6. 有关指针变量的数据类型小结
定义 | 含义 |
int * p | p为指向整形数据的指针变量 |
int * p[n] | 定义指针数组p,它由n个指向整形数据的指针元素组成 |
int (*p)[n] | p为指向含有n个元素的一维数组的指针变量 |
int f() | f 为返回值为整型数值的函数 |
int * p() | p为返回一个指针的函数,该指针指向整型数据 |
int (*p)() | p 为指向函数的指针,该函数返回一个整型数 |
int ** p | p 是一个指针变量,它指向一个指向整形数据的指针变量 |
7. 指针应用程序设计举例
例14:编写交换两个变量值的函数,并调用该函数对3个数按升序排列(不能使用全局变量传递数据)
#include<stdio.h>
void swap(int *pa,int *pb){
int temp;
if(*pa<*pb){
temp=*pa;
*pa=*pb;
*pb=temp;
}
}
main(){
int a,b,c;
printf("please input three numbers:/n");
scanf("%d,%d,%d",&a,&b,&c);
printf("the changed secquence is:/n");
swap(&a,&b);
swap(&a,&c);
swap(&b,&c);
printf("%d %d %d/n",a,b,c);
}
例15:编写求3个数中最大数的函数,并调用该函数求出主函数中3个数中的最大数(不能使用全局变量或return语句传递数据)
#include<stdio.h>
void swap(int *pa,int *pb,int *pc){
if(*pa<*pb)*pa=*pb;
if(*pc>*pa)*pa=*pc;
}
main(){
int a,b,c;
printf("please input three numbers:/n");
scanf("%d,%d,%d",&a,&b,&c);
printf("the maximum is:/n");
swap(&a,&b,&c);
printf("max=%d/n",a);
}
例16:通过键盘输入10个整数存入一维数组中,再按反序输出(要求用指针访问数组元素)
main(){
int a[10],i;
int *p;
printf("please input ten numbers:/n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
p=a+9;
for(i=0;i<10;i++){
printf("%d ",*p);
p--;
}
printf("/n");
}
例17:通过键盘输入一个字符串,判断是否为回文(要求用指针访问数组元素)
#include<stdio.h>
main(){
char a[100],len;
char *pbegin,*pend;
printf("please input a character:/n");
gets(a);//获取字符串的长度
len=strlen(a);
pbegin=a;
pend=a+len-1;
while(pbegin<pend){
if(*pbegin==*pend){
pbegin++;
pend--;
}
else break;
}
if(pbegin>=pend)
printf("Yes/n");
else
printf("No/n");
}
例18:编写字符串复制的函数(要求用指针实现),并调用此函数复制一个字符串
#include<stdio.h>
void scopy(char *a,char *b){
char *pa,*pb;
pa=a;
pb=b;
while((*pb=*pa)!='/0'){
pa++;
pb++;
}
}
main(){
char a[80],b[80];
printf("please input a character:/n");
gets(a);
scopy(a,b);
printf("the character of b is:/n");
puts(b);
}
例19:编写连接两个字符串的函数(要求用指针实现),并调用此函数连接两个字符串。
需注意字符串最后'/0'的处理。
#include<stdio.h>
void scat(char *a,char *b){
char *pa,*pb;
int len_a=strlen(a),len_b=strlen(b);
pa=a;
pb=b;
while(*pa!='/0')pa++;
while(*pb!='/0'){
*pa=*pb;//未赋值'/0'
pa++;
pb++;
}
*pa='/0';
}
main(){
char a[80],b[80];
printf("please input the first character:/n");
gets(a);
printf("please input the second character:/n");
gets(b);
scat(a,b);
printf("the changed character is:/n");
puts(a);
printf("/n");
}
例20:编写将一个字符串前后倒置的函数(要求用指针实现),并调用此函数讲一个字符串前后倒置。
#include<stdio.h>
void schange(char *a){
char *pa,*pb,*p;
int len=strlen(a),mid=(len-1)/2;
int temp;
pa=a;
pb=pa+len-1;
p=pa+mid;
while(pa<p){
temp=*pa;
*pa=*pb;
*pb=temp;
pa++;
pb--;
}
}
main(){
char a[80];
printf("please input the first character:/n");
gets(a);
schange(a);
printf("the changed character is:/n");
puts(a);
printf("/n");
}