C语言程序设计之指针

8.1 指针是什么?

如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。由于通过地址能找到所需的变量单元,可以说,地址指向变量单元。将地址形象地称为指针。

8.2指针变量

8.2.1 使用指针变量的例子

例 通过指针变量访问整型变量。

#include <stdio.h>
int main()
{
int a =100,b = 10;
int *pointer_1,*pointer_2;
pointer_1 = &a;
pointer_2= & b;
printf("a=%d,b=%d\n",a,b);
printf("* pointer_1=%d,*pointer_2=%d\n",*pointer_1,*pointer_2);
return 0;
}

8.2.2 怎样定义指针变量

定义指针变量的一般形式为:
类型名 * 指针变量名;

8.2.3 怎样引用指针变量

(1)给指针变量赋值。
(2)引用指针变量指向的变量
(3)引用指针变量的值
例· 输入a和b两个整数,按先大后小的顺序输出a和b。

#include <stdio.h>
int main()
{
int *p1,*p2,*p,a,b;
printf("please input two integer number:";
scanf("%d%d",&a,&b);
p1=&a;
p2=&b;
if(a<b)
{
p=p1;
p1=p2;
p2=p;
}
printf("a=%d,b=%d",a,b);
printf("max=%d,min=%d",*p1,*p2);
return 0;
}

8.2.4 指针变量作为函数参数
例 输入a和b两个整数,按先大后小的顺序输出a和b。先用函数处理,而且用指针类型的数据作函数参数。

#nclude <stdio.h>
int main()
{
void swap(int *p1,int *p2);
int a,b;
int *p1,*p2;
printf("please input two integer number");
scanf("%d%d",&a,&b);
p1=&a;
p2=&b;
if(a<b)
swap(p1,p2);
printf("max=%d,min=%d",a,b);
return 0;
}
void swap(int *p1,int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}

例 对输入的两个整数按大小顺序输出。

#nclude <stdio.h>
int main()
{
void swap(int *p1,int *p2);
int a,b;
int *p1,*p2;
printf("please input two integer number");
scanf("%d%d",&a,&b);
p1=&a;
p2=&b;
if(a<b)
swap(p1,p2);
printf("max=%d,min=%d",a,b);
return 0;
}
void swap(int *p1,int *p2)
{
int *t;
t=p1;
p1=p2;
p2=t;
}

例 输入3个整数,a,b,c,要求由大到小的顺序把它们输出。用函数实现。

#include <stdio.h>
int main()
{
void exchange(int *q1,int *q2,int *q3);
int a,b,c,*p1,*p2,*p3;
printf("please input two integer number");
scanf("%d%d%d",&a,&b,&c);
p1=&a;
p2=&b;
p3=&c;
exchange(p1,p2,p3);
printf("the order is:   %d,%d,%d\n",a,b,c);
return 0;
}
void exchange(int *q1,int *q2,int *q3)
{
void swap(int *p1,int *p2);
if(*q1<*q2) swap(q1,q2);
if(*q1<*q3)swap(q1,q3);
if(*q2<*q3)swap(q2,q3);
}
void swap(int *p1,int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}

8.3 通过指针引用数组

8.3.1 数组元素的指针

所谓数组元素的指针就是数组元素的地址

8.3.2 在引用数组元素时指针的运算

(1)如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素
(2)如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址,或者说它们指向a数组序号为i的元素。
(3)(p+i)或(a+i)是p+i或a+i所指向的数组元素,即a[i]。
(4)如果指针变量p1和p2都指向同一数组,如执行p2-p1,结果是p2-p1的值(两个地址之差)除以数组元素的长度。
8.3.3 通过指针引用数组元素
引用一个数组元素,可以用以下两种方法:
(1)下标法,如a[i]形式
(2)指针法,如*(a+i)或*(p+i)
例 有一个整型数组a,有10个元素,要求输出数组中的全部元素。
(1)下标法

#include <stdio.h>
int main()
{
int a[10];
int i;
printf("please enter 10 integer number:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++)
printf("%d",a[i]);
printf("\n");
return 0
}

(2)通过数组名计算数组元素地址,找出元素的值。

#include <stdio.h>
int main()
{
int a[10];
int i;
printf("please enter 10 integer number:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++)
printf("%d",*(a+i));
printf("\n");
return 0
}

(3)用指针变量指向数组元素

#include <stdio.h>
int main()
{
int a[10];
int i,*p;
printf("please enter 10 integer number:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(p=a;p<(a+10);p++)
printf("%d",*p);
printf("\n");
return 0
}

8.3.4 用数组名作函数参数

例 将数组a中n个整数按相反顺序存放。

#include <stdio.h>
int main()
{
void inv(int x[],int n);
int i,a[10]={3,7,9,11,8,0,4,6,5,3};
printf("the original array:\n");
for(i=0;i<10;i++)
printf("%d",a[i]);
printf("\n");
inv(a,10);
printf("The array has been inverted:\n");
for(i=0;i<10;i++)
printf("%d",a[i]);
return 0;
}
void inv(int x[],int n)
{
int i,j,m,t;
m=(n-1)/2;
for(i=0;i<=m;i++)
{
j=m-i-1;
t=x[i];
x[i]=x[j];
x[j]=t;
}
}

#include <stdio.h>
int main()
{
void inv(int*x,int n);
int i,a[10]={3,7,9,11,8,0,4,6,5,3};
printf("the original array:\n");
for(i=0;i<10;i++)
printf("%d",a[i]);
printf("\n");
inv(a,10);
printf("The array has been inverted:\n");
for(i=0;i<10;i++)
printf("%d",a[i]);
return 0;
}
void inv(int *x,int n)
{
int *i, *j,m,t,*p;
i=x;
m=(n-1)/2;
p=x+m;
j=x+n-1;
for(;i<=p;i++,j--)
{
t=*i;
*i=*j;
*j=t;
}
}

#include <stdio.h>
int main()
{
void inv(int*x,int n);
int i,arr[10],*p=arr;
printf("the original array:\n");
for(i=0;i<10;i++,p++)
scanf("%d",*p);
printf("\n");
p=arr;
inv(a,10);
printf("The array has been inverted:\n");
for(p=arr;p<arr+10;p++)
printf("%d",*p);
return 0;
}
void inv(int *x,int n)
{
int *i, *j,m,t,*p;
i=x;
m=(n-1)/2;
p=x+m;
j=x+n-1;
for(;i<=p;i++,j--)
{
t=*i;
*i=*j;
*j=t;
}
}

例 用指针方法对10个整数按由大到小排序。

#include <stdio.h>
int main()
{
void sort(int x[],int n);
int i,*p,a[10];
p=a;
for(i=0;i<10;i++)
scanf("%d",p++);
p=a;
sort(p,10);
for(p=a,i=0;i<10;i++)
{
printf("%d",*p);
p++;
}
printf("\n");
return 0;
}
void sort(int x[],int n)
{
int i,j,t,k;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(x[k]<x[j])
k=j;
if(k!= i)
{
t=x[i];
x[i]=x[k];
x[k]=t;
}
}
}

8.3.5 通过指针引用多维数组

1.多维数组元素的地址
2.指向多维数组元素的指针变量
(1)指向数组元素的指针变量
例 有一个3*4 的二维数组,要求用指向元素的指针变量输出二维数组各元素的值。

#include <stdio.h>
int main()
{
int a[3][4]={1,3,5,7,9,11,13,14,15,17,18,19};
int *p;
for(p=a[0];p<a[0]+12;p++)
{
if((p=a[0])%4==0)
printf("\n");
printf("%4d",*p);
}
printf("\n");
return 0;
}

(2)指向由m个元素组成的一维数组的指针变量
例 输出二维数组任一行任一列元素的值。

#include <stdio.h>
int main(){
int a[3][4]={1,3,5,7,9,11,13,14,15,17,18,19};
int (*p)[4],i,j;
p=a;
printf("please enter row and colum:");
scanf("%d,%d",&i,&j);
printf("a[%d,%d] = %d\n",i,j,*(*(p+i)+j));
return 0;
}

3.用指向数组的指针作函数参数
例 有一个班,3个学生,各学4门课,计算总平均分数以及第n个学生的成绩。

#include <stdio.h>
int main()
{
void average(float*p,int n);
void search(float (*p)[4],int n);
float score[3][4] = {{65,65,67,45},{45,45,56,65},{56,67,56,45}};
average(*score,12);
search(score,2);
return 0;
}
void average(float*p,int n)
{
float sum=0,*p_end,average;
p_end=p+n-1;
for(;p<=p_end;p++)
sum+=(*p);
average = sum/n;
printf(""average = %5.2f",averager);
}
void search(float (*p)[4],int n)
{
int i;
printf("The score of No. %d are : \n",n);
for(i=0;i<4;i++)
printf("%5.2f",*(*(p+n)+i));
printf("\n");
}

例 有一个班,3个学生,各学4门课,查找有一门以上课程不及格的学生,输出她们的全部课程的成绩。

#include <stdio.h>
int main()
{
void search(float (*p)[4],int n);
float score[3][4] = {{65,65,67,45},{45,45,56,65},{56,67,56,45}};
search(score,3);
return 0;
}
void search(float (*p)[4],int n)
{
int flag,i,j;
for(j=0;j<n;j++)
{
flag=0;
for(i=0;i<4;i++)
if(*(*(p+j)+i)<60)
flag++;
if(flag>1)
{
printf("No.%d fails,his score are:\n",j+1);
for(i=0;i<4;i++)
printf("%5lf",*(*(p+j)+i));
printf("\n");
}
}
}

8.4 通过指针引用字符串

8.4.1 字符串的引用方式

(1)用字符数组存放一个字符串,可以通过数组名和下标引用字符串中的一个字符,也可以通过数组名和格式声明“%s”输出该字符串。
例 定义一个字符数组,在其中存放字符串“I love China!”,输出该字符串和第8个字符。

#include <stdio.h>
int main()
{
char string[] = "I love China!";
printf("%s\n",string);
printf("%c\n",string[7]);
return 0;
}

例 通过字符指针变量输出一个字符串。

#include <stdio.h>
int main()
{
char *string = "I love China!"
printf("%s\n",string);
return 0;
}

例 将字符串a复制到字符串b,然后输出字符串b;

#include <stdio.h>
int main()
{
char a[] = "I am a student",b[20];
int i;
for(i=0;*(a+i)!='\0';i++)
*(b+i)=*(a+i);
*(b+i) = '\0';
printf("string a is :%s\n",a);
printf("string b is:");
for(i=0;b[i]!='\0';i++)
printf("%c",b[i]);
printf("\n");
return 0;
}

#include <stdio.h>
int main()
{
char a[] = "I am a student",b[20],*p1,*p2;
p1=a;
p2 = b;
for(;*p1!='\0';p1++,p2++)
*p2=*p1;
*p2='\0';
printf("string a is :%s\n",a);
printf("string b is: %s\n",b);
return 0;
}

8.4.2 字符指针作函数参数
例 用函数调用来实现字符串的复制
(1)用字符数组名作函数参数

#include <stdio.h>
int main()
{
void copy_string(char from[],char to[]);
char a[] ="I am a student";
char b[] = "I am a teacher";
printf("string a = %s\n string b = %s\n",a,b);
copy(a,b);
printf("string a = %s\n string b = %s\n",a,b);
return 0;
}
void copy_string(char from[],char to[])
{
int i=0;
while(from[i]!='\0')
{
to[i]=from[i];
i++
}
to[i]='\0';
}

or
(2)用字符型指针变量作实参

#include <stdio.h>
int main()
{
void copy_string(char from[],char to[]);
char a[] ="I am a student";
char b[] = "I am a teacher";
char* from =a;
char* to = b;
printf("string a = %s\n string b = %s\n",a,b);
copy(from,to);
printf("string a = %s\n string b = %s\n",a,b);
return 0;
}
void copy_string(char from[],char to[])
{
int i=0;
while(from[i]!='\0')
{
to[i]=from[i];
i++
}
to[i]='\0';
}

or
(3)用字符指针变量作形参和实参

#include <stdio.h>
int main()
{
void copy_string(char *from,char *to);
char a[] ="I am a student",* from;
char b[] = "I am a teacher",* to;
from =a;
to= b;
printf("string a = %s\n string b = %s\n",a,b);
copy(a,b);
printf("string a = %s\n string b = %s\n",a,b);
return 0;
}
void copy_string(char *from,char *to)
{
for(;*from!='\0';from++,to++)
*to = *from;
*to='\0';
}

8.4.3 使用字符指针变量和字符数组的比较

(1)字符数组由若干个元素组成,每个元素中存放一个字符,而字符指针变量中存放的是地址(字符串第i个字符的地址),绝不是将字符串放到字符指针变量中

(2)赋值方式。可以对字符指针变量赋值,但不能对数组名赋值。
可以采用以下方式对字符指针变量赋值
char *a;
a=“I love China”;
不能用以下办法对字符数组名赋值
char str[14];
str[0]=‘I’;
str=“I love China”;

(3)初始化的含义。对字符指针变量赋初值。
数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值。

(4)存储单元的内容。编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配了一个存储单元。

(5)指针变量的值是可以改变的,而数组名代表一个固定的值(数组首元素的地址),不能改变

(6)字符数组中各元素的值是可以改变的(可以对它们再赋值),但字符指针变量指向的字符串常量中的内容是不可以被取代的(不能对它们再赋值)。如:
char a[] =“House”;
char *b = “House”;
a[2] = ‘r’; //合法
b[2] =‘r’; //非法,字符串常量不能改变

(7)引用数组元素。对字符数组可以用下标法(数组名和下标)引用一个数组元素(如a[5]),也可以用地址法(如*(a+5))引用数组元素a[5]。如果定义了字符指针变量p,并使它指向数组a的首元素,则可以用指针变量带下标的形式引用数组元素,如p[5],同样,可以用地址法如*(p+5)引用数组元素a[5]

(8)用指针变量指向一个格式化字符串,可以用它代替prinf函数中的格式字符串。例如,
char* format;
format = “a=%d,b=%f\n”;
printf(format,a,b);

8.5 指向函数的指针

8.5.1 用函数指针变量调用函数

8.5.2 什么是函数指针

例 用函数求整数a和b中的大者
(1)通过函数名调用函数

#include <stdio.h>
int main()
{
int max(int ,int );
int a,b,c;
printf("please input a and b\n");
scanf("%d%d",&a,&b);
c=max(a,b);
printf("max=%d\n",c);
return 0;
}
int max(int x ,int y )
{
int z;
z=x>y?x:y;
return z;
}

(2)通过指针变量访问它指向的函数

#include <stdio.h>
int main()
{
int max(int ,int );
int (*p)(int int );
p=max;
int a,b,c;
printf("please input a and b\n");
scanf("%d%d",&a,&b);
c=(*p)(a,b);
printf("max=%d\n",c);
return 0;
}
int max(int x ,int y )
{
int z;
z=x>y?x:y;
return z;
}

8.5.3 怎样定义和使用指向函数的指针变量

定义指向函数的指针变量一般形式为:
类型名(* 指针变量名)(函数参数表列)
例 输入两个整数,然后让用户选择1或2,选1时调用max函数,输出二者大树,选择2时调用min函数,输出二者中的小数。

#include <stdio.h>
int main()
{
int max(int , int);
int min(int ,int);
int a,b,c;
printf("please enter two numbers\n");
scanf("%d%d",&a,&b);
printf("please choose 1 or 2\n");
scanf("%d",&c);
if("c==1")
printf("max=%D\n",max(a,b));
else if("c==2")
printf("min=%D\n",min(a,b));
return 0;
}
int max(int x, int y)
{
int max;
max=x>y?x:y;
return max;
}
int min(int ,int)
{
int min;
max=x<y?x:y;
return min;
}

8.5.4 用指向函数的指针作函数参数

例 输入两个整数a和b,然后让用户选择1或2,选1时调用max函数,输出二者大树,选择2时调用min函数,输出二者中的小数,输入3时调用a和b的和。

#include <stdio.h>
int main()
{
int max(int , int);
int min(int ,int);
int add(int ,int);
int fun(int x,int y, int (* p)(int, int));
int a,b,c;
printf("please enter two numbers\n");
scanf("%d%d",&a,&b);
printf("please choose 1 ,2 or 3\n");
scanf("%d",&c);
if("c==1")
fun(a,b,max);
else if("c==2")
fun(a,b,max);
else if("c==3")
fun(a,b,sum);
return 0;
}
int max(int x, int y)
{
int max;
max=x>y?x:y;
printf("max=");
return max;
}
int min(int ,int)
{
int min;
max=x<y?x:y;
printf("min=");
return min;
}
int add(int x ,int y)
{
int sum;
sum =x+y;
printf("sum=");
return sum;
}
int fun(int x,int y, int (* p)(int, int))
{
int result;
result=(*p)(x,y);
printf("%d\n",result);
}

8.6 返回指针值的函数

定义返回指针值的函数的一般定义为:
类型名 *函数名(参数表列);
例 有a个学生,每个学生有b门课程的成绩。要求在用户输入学生序号以后,能输出该学生的全部成绩。用函数指针来实现。

#include <stdio.h>
int main()
{
float * search(int n,float (*p)[]4)
float score[][4]={{44,44,56,33},{76,67,56,76},{45,56,67,56},{56,76,78,67}};
int n,i;
float* p;
printf("please enter the number of student:");
scanf("%d",&n);
p=search(n,score);
for(i=0;i<4;i++)
printf("%5f",*(p+i));
printf("\n");
return 0;
}
float * search(int n,float (*p)[4])
{
int *q;
q=*(p+n);
return q;
}

例 有a个学生,每个学生有b门课程的成绩,找出其中有不及格的课程的学生。

#include <stdio.h>
int main()
{
float * search(int n,float (*p)[]4)
float score[][4]={{44,44,56,33},{76,67,56,76},{45,56,67,56},{56,76,78,67}};
int j,i;
float* p;
for(i=0;i<4;i++)
{
p=search(score+i);
if(p==*(score+i))
{
printf("No.%d score:",i);
for(j=0;j<4;j++)
printf("%5.2f",*(p+j));
printf("\n");
}
}
printf("\n");
return 0;
}
float * search(float (*p)[4])
{
float *pt =NULL;
int i;
for(i=0;i<4;i++)
if(*(*p+i)<60)
pt=*p;
return pt;
}

8.7 指针数组和多种数组

8.7.1什么是指针数组

一个数组,若其元素均为指针数组类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。
定义一维指针数组的一般形式为:
类型名 *数组名[数组长度]
例 将若干字符串按字母顺序(由小到大)输出

#include <stdio.h>
#include <string.h>
int main()
{
void sort(char * name[],int n);
void print(char *name[],int n);
char *name[] ={"follow me","fortran","basic","great wall","computer design"};
int n =5;
sort(name,n);
print(name,n );
return 0;
}
void sort(char * name[],int n)
{
int i,j,k;
char * temp;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(strcmp(name[k],name[j])>0)k=j;
if(k!=i)
{
temp=name[i];
name[i]=name[k];
name[k]=temp;
}
}
}
void print(char *name[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%s\n",name[i]);
}

8.7.2 指向指针数据的指针

例 使用指向指针数据的指针变量

#include <stdio.h>
int main(){
char *name[] ={"follow me","fortran","basic","great wall","computer design"};
char **p;
int i;
for(i=0;i<5;i++)
{
p=name+i;
printf("%s\n",*p);
}
return 0;
}

例 有一个指针数组,其元素分别指向一个整型数组的元素,用指向指针数据的指针变量,输出整型数组各元素的值。

#include <stdio.h>
int main()
{
int a[5] = {1,3,5,7,9};
int *num[5] = {&a[0],&a[1],&a[2],&a[3],&a[4]};
int **p,i;
p=num;
for(i=0;i<5;i++)
{
printf("%d",**p);
p++;
}
return 0;
}

8.8 动态内存分配与指向它的指针变量

8.8.1 什么是内存的动态分配

全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的,这个存储区十一个称为栈的区域。除此之外,C语言还允许建立内存分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不等到函数结束时释放,而是需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为堆区。可以根据需要,向系统申请所需大小的空间。由于未在声明部分定义它们为变量或数组,因此不能通过变量名或数组名去引用这些数据,只能通过指针来引用。

8.8.2 怎样建立内存的动态分配

1.使用malloc函数
其函数原型为:
void *malloc(unsigned int size);

2.使用calloc函数
其函数原型为:
void *calloc(unsigned n,unsigned size);

3.使用free函数
其函数原型为:
void free(void *p);

4.使用realloc函数
其函数原型为:
void realloc(void p;unsigned int size);

例 建立一个动态数组,输入5个学生的成绩,另外用一个函数检查其中有无低于60分的,输出不及格的成绩。

#include <stdio.h>
#include <stdlib.h>
int main()
{
void check(int *);
int *p,i;
p=(int*)malloc(5*sizeof(int));
for(i=0;i<5;i++)
scanf("%d",p+i);
check(p);
return 0;
}
void check(int *p)
{
printf("They are fail:");
int i;
for(i=0;i<5;i++)
if(p[i] < 60)printf("%5d",p[i]);
printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值