C语言-第七章、用指针实现程序的灵活设计

 

7_1  指针的基本概念

_1.1   地址与指针 

C语言中通常把地址成为指针。

_1.2  内存单元的指针与内存单元的内容

_1.3  变量的指针

变量的指针就是变量的地址

_1.4  直接访问与间接访问

7_2  指向变量的指针变量

_2.1  指针变量的定义

形式:基类型说明符  *变量名                   如:int  *p1

“*”也是一个说明符,p1是一个指针变量。

_2.2  指针变量的引用

1.  指针的专用运算符

 

(1) 取地址运算符&             例:&变量名

(2)指针运算符*                    例:*变量名

2.指针变量的赋值

(1)指针变量的初始化

int a;
int *ap=&a;    /*定义指向整体变量a的指针变量ap*/

(2) 赋值语句:

①int *ap=&a,a;   /*错误,不能把未定义的变量a的地址赋给ap*/
/*不允许把一个数赋予指针变量,被赋值的指针变量前也不能再加“*”说明符。*/
//②错例:
int  *p;
p=1000;        /*不能把一个数赋予指针变量*/
*p=&a;         /*被赋值的指针变量前不能再加“*”说明符*/

(3)将已被赋值的指针变量的值赋给另一指针变量

int a,*ap,*bp;
ap=&a;       /*使指针变量ap指向变量a*/
bp=ap;       /*将指针变量ap的值赋给指针变量bp;执行该语句后ap和bp都指向同一变量a*/

注:只有相同类型的指针变量之间可以相互赋值。

错例:

int a=3,*ap=&a;
float bp;
bp=ap;     /*错误,指针变量bp只能指向float型变量(只能保存float型变量的地址)*/

(4) 可以给指针变量赋0值如:

char  *p=0;

该指针称为空指针,为了程序的可读性,通常符号常量NULL来表示空指针的值。如:

char *p=NULL;

3.  指针变量加减一个整数

一个指针加一个整数,表示将指针后移;相反,一个指针减一个整数,表示将指针前移。

4.  两个同类指针变量相减

用于数组,差值表示两个指针变量之间相隔的元素个数

5.  两个同类指针变量作比较运算

用于判断先后关系

6.  指针变量的引用举例

【例7-1】 通过指针变量引用变量的值

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

例7-2】 指针变量及其简单运算

#include<stdio.h>
int main()
{
    int x=3,y,*xp=&x;
	y=*xp+5;
	printf("y=%d\n",y);
	y=++*xp;
	printf("%d\n",y);
	y=*xp++;
	printf("x=%d,y=%d\n",x,y);     /*表示把x的值赋给y再使xp后移,即等价于y=*xp;xp++;*/
	return 0;
}

注:“++”和“*”的运算优先级相同且都是自右向左。

_2.2  指针变量作为函数参数

【例7-3】 用一般变量作为参数,不能实现交换。

#include<stdio.h>
int main()
{
    int swap(int x,int y);
	int a=100,b=10;
	printf("%d,%d\n",a,b);
	swap(a,b);
	printf("%d,%d\n",a,b);
	return 0;
}
int swap(int x,int y)  /*交换指针变量ap,bp所指向是地址单元中的内存*/
{
    int temp;
	temp=x;
	x=y;
	y=temp;
}

【例7-4】若改写为指针函数为参数即可交换。

#include<stdio.h>
int main()
{
    int swap(int *ap,int *bp);
	int a=100,b=10;
	printf("%d,%d\n",a,b);
	swap(&a,&b);
	printf("%d,%d\n",a,b);
	return 0;
}
int swap(int *ap,int *bp)  /*交换指针变量ap,bp所指向是地址单元中的内存*/
{
    int temp;
	temp=*ap;
	*ap=*bp;
	*bp=temp;
}

7_3指针与数组

_3.1  指针与一维数组

1.  指向数组元素的指针变量

形式:基类型说明符  *指针变量  如:

int a[10];
int *p;
p=&a[0];

C语言规定,把数组的首地址称为数组的指针。

(1)p、a、&a[0]均指向同一单元,它们是数组a的首地址,但是p是指针变量,而a、&a[0]都是指针常量。

2.  通过指针引用数组元素

三种方法:①下标法         ②常量指针法           ③指针变量法。

(1)下标法

#include<stdio.h>
int main()
{
	int a[5],i;
	printf("Please input 5 numbers:");
    for (i=0;i<5;i++)
		scanf("%d",&a[i]);
	for (i=0;i<5;i++)
		printf("a[%d]=%-4d",i,a[i]);
	printf("\n");
	return 0;
}

(2)常量指针法:

#include<stdio.h>
int main()
{
	int a[5],i;
	printf("Please input 5 numbers:");
    for (i=0;i<5;i++)
		scanf("%d",a+i);
	for (i=0;i<5;i++)
		printf("a[%d]=%-4d",i,*(a+i));
	printf("\n");
	return 0;
}

(3)指针变量法:

#include<stdio.h>
int main()
{
	int a[5],i,*p=a;
	printf("Please input 5 numbers:");
    for (i=0;i<5;i++)
		scanf("%d",p+i);
	for (i=0;i<5;i++)
		printf("a[%d]=%-4d",i,*(p+i));
	printf("\n");
	return 0;
}

(4)指针带下标法:

#include<stdio.h>
int main()
{
	int a[5],i,*p=a;
	printf("Please input 5 numbers:");
    for (i=0;i<5;i++)
		scanf("%d",&p[i]);
	for (i=0;i<5;i++)
		printf("a[%d]=%-4d",i,p[i]);
	printf("\n");
	return 0;
}

(5)逐个移动指针法:

#include<stdio.h>
int main()
{
	int a[5],i,*p=a;
	printf("Please input 5 numbers:");
    for (i=0;i<5;i++)
		scanf("%d",p++);
	p=a;
	for (i=0;i<5;i++)
		printf("a[%d]=%-4d",i,*p++);
	printf("\n");
	return 0;
}

3.用数组的指针作为函数的参数

【例7-7】用冒泡法对10个整数按升序排列

#include<stdio.h>
#define N 5
int main()
{
	void output(int *p,int n);
	void sort (int x[],int n);
	int a[N],i,*p;
	printf("请输入%d个整数:\n",N);
    for (i=0;i<N;i++)
		scanf("%d",&a[i]);
	printf("\n");
	printf("原数组如下:\n");
	output (a,N);
    p=a;
	sort (p,N);
	printf("升序结果如下:\n");
    output (a,N);
	return 0;
}
void output (int *p,int n)
{   int i;
    for(i=0;i<n;i++)
		printf("%-4d",*(p+i));
	printf("\n");
}
void sort (int x[],int n)
{   int i,j,k,t;
    for(i=0;i<n-1;i++)
	{
		for (j=0;j<n-i-1;j++)
			if (x[j]>x[j+1])
			{t=x[j];x[j]=x[j+1];x[j+1]=t;}
	}
}

_3.2  指针与多维数组

1.多维数组的地址

2.指向二维数组元素的指针变量

【例7-9】用指针变量输入多维数组的值

#include<stdio.h>
int main()
{
	int a[2][3]={{1,2,3},{4,5,6}},i;
	int *p=a[0];
    for (i=0;i<6;i++)
	{
		printf("%-4d",p[i]);
		if ((i+1)%3==0)  printf("\n");
	}
	return 0;
}

3.指向一维数组的指针变量

形式:类型说明符  (*指针变量名)[长度];如:

int (*p)[3];

【例7-10】用指向一维数组的指针变量输出二维数组中的各元素值。

#include<stdio.h>
int main()
{
	int a[2][3]={1,2,3,4,5,6};
	int *(p)[3];
    int i,j;
    for (i=0;i<2;i++)
	{
	    for (j=0;j<3;j++)
			printf("%-4d",*(*(p+i)+j));
		printf("\n");
	}
	return 0;
}

7_4  字符串与指针

_4.1  字符指针的定义与引用

对指向字符变量的指针变量应赋予该字符变量的地址。如:

char  c,*p=&c;

对指向字符串的指针变量应赋予一个字符串的首地址,如:

char  c,*p="China";

等效于:char  *p;     p="China";

【例7-11】用字符指针处理字符数组中的字符串

#include<stdio.h>
int main()
{
    char s[]="China";
	char *p=s;
    while (*p!='\0')
    {
    putchar(*p);
    p++;
    }
    printf("\n");
    return 0;
}

【例7-12】用字符指针处理字符串

#include<stdio.h>
int main()
{
    char s[]="China";
	char *p=s;
    printf("%s\n",p);
    return 0;
}

_4.2  字符指针作为函数参数

【例7-14】对字符串内容作修改

#include<stdio.h>
void change (char *s)
{
   s[2]='r';
}
int main()
{    char a[]="file";
     change (a);
	 printf("%s\n",a);
	 return 0;
}
    

7_5  指针数组

_5.1  用指针数组处理二维数组

【例7-15】  用指针数组处理二维数组

#include<stdio.h>
int main()
{
    int a[2][3]={{1,2,3},{4,5,6}},i,j;
	int *pa[2];         /*定义数组pa,它的两个数组pa[0]和pa[1]都是存放指针变量的*/
	pa[0]=a[0];
	pa[1]=a[1];
	for (i=0;i<2;i++)
    {    for (j=0;j<3;j++)
	    printf("%-4d",*(pa[i]+j));
		printf("\n");
	}
    return 0;
}

_5.2  用字符指针数组处理一组字符串

【例7-16】  用冒泡法对字符按字母顺序升序排列

#include<stdio.h>
#include<string.h>
void sort (char *a[],int n)
{   int i,j;
    char *t;
	for (i=0;i<n-1;i++)
		for (j=0;j<n-i-1;j++)
		if (strcmp (a[j],a[j+1])>0)
		{t=a[j];a[j]=a[j+1];a[j+1]=t;}
}
int main()
{   char *p[5]={"Basic","Pascal","Fortran","C","Java"};
    int i;
	sort (p,5);
	for(i=0;i<5;i++)
		printf("%s\n",p[i]);
	return 0;
}

 

7_6  指向指针的指针

二级指针的定义格式:  类型说明符  **指针变量名;  如:

int  **p;

#include<stdio.h>
int main()
{   char *pa[5]={"Basic","Pascal","Fortran","C","Java"};
    char **p;
	p=pa;
	while (pa<pa+5)
	{
		printf("%s\n",*p);
		p++;
	}
	return 0;
}

 

 

 

7_7  指针与函数

_7.1  指针型函数

指针型函数:返回指针值的函数

形式:类型说明符  *函数名(形参表列)

{

……         /*函数体*/

}

【例7-18】输入一个1~7之间的函数,输出对应星期名的英语单词。

#include<stdio.h>
char *day_name(int n)
{
	char *name[]={"Monday ","Tuseday","Wednesday","Thursday","Friday","Saturday","Sunday"};
	return (name[n-1]);
}
int main()
{   int i;
    char *day_name(int n);
	printf("\t星期名对应的英文单词查询\n请输入一个1~7之间的整数:");
	scanf("%d",&i);
	while (i<1||i>7)
	{
		printf("出错!,请重新输入:");
		scanf("%d",&i);
	}
	printf("星期%d对应的英语单词:%s\n",i,day_name(i));
	return 0;
}

_7.2  指向函数的指针变量

格式:类型说明符 (*指针变量名)();如:

int  (*p)();

 

【例7-19】 求两数较大者

#include<stdio.h>
int max(int a,int b)
{   if(a>b)
    return a;
    else return b;
}
int main()
{
	int x,y,z;
	int (*p)();
	p=max;
	printf("请输入两个整数(用逗号分隔):\n");
    scanf("%d,%d",&x,&y);
	z=(*p)(x,y);
	printf("两数中较大者为:%d\n",z);
	return 0;
}

 

7_8  指针应用过程中的注意事项

1.  要准确理解指针的含义,区别指针和指针变量的不同含义。

2.  在对数组进行操作时,要能正确的使用指针。

3.  读者须对各种有关的指针变量定义形式加深理解。

4.  void指针,即“指向空类型的指针”,是指不指向具体数据对象的指针。

5.  指针还可以实现对动态分配的内存空间进行有效的管理。

 

C语言中,常用malloc()和free()这两个函数以及sizeof运算符动态分配和释放内存空间。

malloc()函数和free()函数所需的信息通常在头文件stdio.h 中,其函数原型及功能如下:

(1)malloc()函数

函数原型:

void  *malloc (unsigned size)

功能:从内存分配一个大小为size个字节的内存空间。如果分配成功,返回新分配内存的首地址;如果没有足够的内存分配,则返回NULL。

为确保内存分配准确,函数malloc()通常和运算符sizeof 一起使用。例:

int *p;
p=(int* )malloc(20*sizeof(int));/*分配20个所需的内存空间*/

(2)  free函数

函数原型:void free(void *p);

功能:释放由指针变量p所指向的内存块,无返回值。如:

int *p;
p=(int* )malloc(20*sizeof(int));/*分配20个所需的内存空间*/
……
free(p);

【例7-20】  输入n名学生的C语言成绩,并将这些成绩逆序输出。

#include<stdio.h>
int main()
{
	float *score;
	int n,i;
	printf("请输入学生人数:");
	scanf("%d",&n);
	score=(float*)malloc(n*sizeof(float));
	if(!score) 
		printf("分配空间失败!\n");
	else 
	{
		printf("请输入%d个学生的成绩(空格分隔):\n",n);
		for (i=0;i<n;i++)
			scanf("%f",score+i);
		printf("逆向输出各成绩如下:\n");
		for (i=n-1;i>=0;i--)
			printf("%7.2f",score[i]);
		printf("\n");
		free(score);
	}
	return 0;
}

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/8824/blog/781985

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值