栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

善于利用指针

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

善于利用指针

指针
  • 指针
  • 直接访问与间接访问
  • 指针变量
    • 定义指针变量
    • 引用指针变量
  • 指针变量作为函数参数
  • 通过指针引用数组
    • 通过指针引用数组元素
    • 通过指针引用多维数组
    • 字符指针变量和字符数组的比较
  • 指向函数的指针
    • 指向函数的指针的优势
  • 返回指针值的函数
  • 指针数组
  • 例题汇总
    • 例8.1初识指针
    • 例8.2引用指针变量(排序)
    • 例8.3指针变量函数
    • 例8.4指针变量函数的错误示范
    • 例8.5
    • 例8.6通过指针引用数组元素(输出数组元素)
    • 例8.7通过指针输出数组元素(最快读取)
    • 例8.8通过指针引用数组(反顺序)
    • 例8.9用指针变量作参数
    • 例8.10形参采用指针变量(便于理解,推荐使用)
    • 例8.16输出字符串
    • 例8.17采用指针实现字符串输出
    • 例8.18复制字符串
    • 例8.19复制字符串(使用指针变量)
    • 例8.20字符指针作函数参数(复制字符串)
    • 例8.21改变指针变量的值
    • 例8.22通过指针调用函数
    • 例8.23通过指针调用函数
    • 例8.24指向函数的指针
    • 例8.25返回指针的函数
    • 例8.26
    • 例8.27指针数组
    • 例8.28指向指针的指针变量
    • 例8.29

指针

在程序中定义一个变量时,系统会为该变量创建一个存储单元。存储单元的编号被称为地址。程序可以通过地址找到变量,即地址指向变量,因此C语言中将地址形象的称为“指针”。
指针说明了变量的位置信息,但无法确定该变量占用了多少个存储单元。因此若是要有效地存取一个数据,除了需要指针(即位置信息)外,还需要该数据的类型信息,即数据类型。综上所述,C语言中的地址包括位置信息和类型信息两部分,可以称其为“带类型的地址”。
如:a为整型变量,&a一般称它为“变量a的地址”,确切的说,它是“整型变量a的地址”,一般简称“地址”。

直接访问与间接访问
  • 直接访问
    通过变量名进行的访问,称为“直接访问”
    如:
int a = 3;
  • 间接访问
    将变量i的地址存放在另一变量中,然后通过该变量来找到变量i的地址,从而访问变量i。这类专门存放另一个变量的地址的变量,称为“指针变量”。指针变量的值是地址。
指针变量

指针变量是专门用来存放变量的地址(即指针)的变量。指针变量的值是地址。

定义指针变量

定义指针变量的一般形式为:
类型名 * 指针变量名;
一个变量的指针的含义包含两个方面:一是以存储单元编号表示的纯地址;二是它指向的存储单元的数据类型;指向整型数据的指针类型表示为“int *”,读作“指向int的指针”或简称“int 指针”。
例如:

int * pointer_1, * pointer_2;
引用指针变量
  1. 给指针变量赋值:
p = &a;			//把a的地址赋给指针变量p
  1. 引用指针变量指向的变量
* p = 1;				//将整数1赋给p当前所指向的变量
printf("%d", * p);		//输出指针变量p所指向的变量的值
运算符说明
&取地址符,&a是变量a的地址
*指针运算符,* p代表指针变量p指向的对象
指针变量作为函数参数

指针变量作为函数参数,它的作用是将一个变量的地址传送给另一个函数中。可实现,通过调用函数使变量的值发生变化。
见例8.3
为了使函数中改变了的变量值能被主函数所用,应该用指针变量作为函数参数,在函数的执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留了下来,这样就实现了“通过调用函数使变量的值发生变化”

通过指针引用数组

数组元素的指针就是数组元素的地址,通常数组元素的引用采用下标法(即a[i]),也可以是用指针法,即通过指向数组元素的指针找到所需的元素。

p = &a[0];		//p的值是a[0]的地址
p = a;			//与上一句等价,p的值是数组a首元素的地址

数组名其实就是一种指针变量,使用数组名作参数,其实就是传递数组首元素的地址,所以形参其实就是指针变量

void fun(int arr[], int n)		//arr按指针变量处理,等价于void fun(int * arr, int n){}
{
..........
}
通过指针引用数组元素
  • 引用数组元素时指针的运算
    当指针指向数组元素时,才会涉及到指针的运算。
    若指针已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。

  • 引用数组元素

    • 下标法,如a[i]形式;
    • 指针法,如*(a+i)或 *(p+i)。a是数组名,p是指向数组元素的指针变量

使用指针变量直接指向元素,读取速度更快。不必每次都重新计算地址。

通过指针引用多维数组

多维数组

int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};

已知a[0]和*(a+0)等价,a[1]和 (a+1)等价,因此a[0]+1与(a+0)+1都是&a[0][1]

字符指针变量和字符数组的比较
  1. 值不同:字符数组由若干各元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址。
  2. 赋值方式不同:可以对字符指针变量赋值,但不能对数组名赋值。
  3. 初始化的含义不同:数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值。
    如:
char *a;
a = "I love China.";

是合规的

```c
char a[];
a[] = "I love China."

是不合规的
4. 存储单位的内容不同:编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元。
5. 值的改变:指针变量的值时可以改变的,而字符数组名代表一个固定的值,不能改变。
6. 字符数组中各元素的值时可以改变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的。
7. 引用数组元素。数组更方便
8. 用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。

char *format;
format = "a=%d,b=%fn";
printf(format, a, b);

等价于

printf("a=%d,b=%dn", a, b);
指向函数的指针

定义指向函数的指针的一般形式为:
*类型名 (指针变量名)(函数参数表列)

指向函数的指针的优势

每次调用函数时给出不同的函数名最为实参即可,调用函数不必作任何修改。这种方法是符合结构化设计方法原则的。
见例8.24

返回指针值的函数

定义返回指针值的函数的原型为
*类型名 函数名(参数列表)
如:

int *a(int x, int y)
{
	……
}

*的运算级别较低,a(int x, int y)是一个函数。前面的 int *,说明这是一个指数类型的函数

指针数组

指针数组的每一个元素都是指针,即指针数组的每一个元素都存放了一个地址。
指针数组的定义形式为:
*类型名 数组名[数组长度]

例题汇总 例8.1初识指针

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

#include
int main()
{
	int a = 100, b = 10;		//整型变量a,b
	int * pointer_1, * pointer_2;	//指针型变量pointer_1,pointer_2
	
	pointer_1 = &a;				//将整型变量a的地址,存入指针变量pointer_1中
	pointer_2 = &b;				//将整型变量b的指针,存入指针变量pointer_2中
	
	printf("a=%d,b=%dn", a, b);	//输出整型变量的值
	printf("pointer_1=%d,pointer_2=%d", * pointer_1, * pointer_2);
	//输出指针变量的值,*为取值符号,* pointer_1的意思为地址为pointer_1的整型存储单元中的存储的值
	return 0;
}
例8.2引用指针变量(排序)

输入a和b两个整数,按先大后小的顺序输出a和b

#include
int main()
{
	int * p1, * p2, * p, a, b;
	
	printf("请输入两个整数:");
	scanf("%d%d", &a, &b);
	p1 = &a;	//将变量a的地址存入指针变量p1中
	p2 = &b;	//将变量b的地址存入指针变量p2中
	
	if(a < b)	//如果a 
例8.3指针变量函数 

同例8.2

#include
int main()
{
	void swap(int *p1, int *p2);
	int a, b;
	int *pointer_1, *pointer_2;
	
	printf("请输入两个整数:");
	scanf("%d%d", &a, &b);
	pointer_1 = &a;
	pointer_2 = &b;
	
	if(a < b)
		swap(pointer_1, pointer_2);
	
	printf("最大值为:%dn最小值为:%d", a, b);
}

void swap(int *p1, int *p2)
{
	int temp;
	
	temp = *p1;		
	*p1 = *p2;
	*p2 = temp;
	
}


例8.4指针变量函数的错误示范

同例8.2

#include
int main()
{
	void swap(int *p1, int *p2);
	int a, b;
	int *pointer_1, *pointer_2;
	
	printf("请输入两个整数:");
	scanf("%d%d", &a, &b);
	pointer_1 = &a;
	pointer_2 = &b;
	
	if(a < b)
		swap(pointer_1, pointer_2);
	
	printf("最大值为:%dn最小值为:%d", *pointer_1, *pointer_2);
	
	return 0;
}

void swap(int *p1, int *p2)	//swap函数,交换p1与p2的指向
{
	int *p;
	p = p1;
	p1 = p2;
	p2 = p;
}


C语言中实参变量和形参变量之间的数据传递是单向的值传递方式,用指针变量作函数参数时同样要遵循这一规则。不可能通过执行调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。

例8.5

输入3个整数a,b,c要求按由大到小的顺序将它们输出。

#include
int main()
{
	void exchange(int *q1, int *q2, int *q3);	//函数声明,由大到小排列
	int a, b, c, *p1, *p2, *p3;
	
	printf("请输入3个整数:n");
	scanf("%d%d%d", &a, &b, &c);
	p1 = &a;
	p2 = &b;
	p3 = &c;
	
	exchange(p1, p2, p3);
	
	printf("由大到小的顺序为:%d,%d,%d", a, b, c);
	return 0;
}

void exchange(int *q1, int *q2, int *q3)
{
	void swap(int *pt1, int *pt2);		//函数声明,交换两个数
	if(*q1 < *q2)
		swap(q1,q2);
	if(*q1 < *q3)
		swap(q1,q3);
	if(*q2 < *q3)
		swap(q2,q3);
}

void swap(int *pt1, int *pt2)
{
	int temp;
	temp = *pt1;
	*pt1 = *pt2;
	*pt2 = temp;
}
例8.6通过指针引用数组元素(输出数组元素)

有一个整型数组a,有10个元素,输出数组中的全部元素。

#include
int main()
{
	int a[10];
	int *p;
	//int i;
	
	printf("请输入10个整数:n");
	
	for(p=a; p<(a+10); p++)	//直接将输入的数值存入指定的存储单独
		scanf("%d", p);
		
	printf("输入的数组元素为;n");
	for(p=a; p<(a+10); p++)
		printf("%3d", *p);
		
	return 0;
}
例8.7通过指针输出数组元素(最快读取)

同上

#include
int main()
{
	int *p, i, a[10];
	p = a;			//将数组元素a[0]的地址赋值到p中
	
	printf("请输入10个整数:n");
	for(i=0; i<10; i++)
		scanf("%d", p++);	//循环结束后,p的值为(a+10)的地址
	p = a;					//若要正确的输出数组a的元素,需将p指向的地址复原到a[0]上
	for(i=0; i<10; i++)
		printf("%3d", *p++);
	
	printf("n");
	return 0;
}
例8.8通过指针引用数组(反顺序)

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

#include
int main()
{
	void inv(int x[], int n);		//函数声明,交换数组顺序
	int i, a[10] = {3,7,9,11,0,6,7,5,4,2};
	
	printf("原数组内容为:n");
	for(i=0; i<10; i++)
		printf("%3d", a[i]);
	printf("n");
	inv(a, 10);			//运行inv函数
	
	printf("交换后的数组内容为:n");
	for(i=0; i<10; i++)
		printf("%3d", a[i]);
	printf("n");
	
	return 0;
}

void inv(int x[], int n)	//x为数组名
{
	int temp, i, j, m;
	m = (n-1)/2;
	
	for(i=0; i<=m; i++)
	{
		j = n-1-i;
		temp = x[i];
		x[i] = x[j];
		x[j] = temp;
	}
}
例8.9用指针变量作参数

同例8.8

#include
int main()
{
	void inv(int *x, int n);	//函数声明,输入数组名和数组元素个数,交换数组元素
	int i, arr[10], *p=arr;		//若采用指针变量作实参,必须先使指针变量又确定值,指向一个已定义的对象
		
	printf("请输入十个整数:n");
	for(i=0; i<10; i++)
		scanf("%d", p++);
	printf("n");
	
	p = arr;		//将指针p定位到数组元素a[0]上
	inv(p, 10);		//交换拥有10个元素的数组a
	//若采用指针变量作实参,必须先使指针变量又确定值,指向一个已定义的对象
	
	printf("交换顺序后的数组为:n");
	for(i=0; i<10; i++)
		printf("%3d", *p++);
	printf("n");
	return 0;
}

void inv(int *x, int n)	//inv函数,输出数组名和数组元素的个数,交换数元素顺序
{
	int *p, m, temp, *i, *j;
	
	m = (n-1)/2;
	i = x;
	j = x+n-1;
	p = x+m;
	
	for(; i<=p; i++,j--)
	{
		temp = *i;
		*i = *j;
		*j = temp;
	}
}
例8.10形参采用指针变量(便于理解,推荐使用)

对10个整数按由大到小的顺序排序

#include
int main()
{
	void sort(int x[], int n);		//函数声明,输入数组名和数组元素个数, 采用选择法排序
	int i, *p, a[10];
	p = a;
	
	printf("请输入十个整数:n");
	for(i=0; i<10; i++)
		scanf("%d", p++);
	
	p = a;
	sort(p, 10);		//输入数组名和数组元素个数,采用选择法排序
	for(i=0; i<10; i++)
		printf("%3d", *p++);
	return 0;
}

void sort(int x[], int n)	//选择法,由大到小排序
{
	int i, j, k, t;
	
	for(i=0; ix[k])
				k = j;
		if(k!=i)
		{
			t = x[i];
			x[i] = x[k];
			x[k] = t;
		}
	}
}
例8.16输出字符串

定义一个字符数组,在其中存放字符串“I love China”,输出字符串和第8个字符

#include
int main()
{
	char string[] = "I love China!";	//输入字符串
	printf("%sn", string);		//输出字符串
	printf("%cn", string[7]);		//输出字符串第8个元素
	
	return 0;
}
例8.17采用指针实现字符串输出

同例8.16

#include
int main()
{
	char *string = "I love China!"; //将“”
	printf("%sn", string);
	printf("%cn", *(string+7));
	
	return 0;
}

例8.18复制字符串

将字符串a复制为字符串b,然后输出字符串b

#include
int  main()
{
	char a[] = "I am a student.";
	char b[20];
	int i;
	
	for(i=0; *(a+i)!=''; i++)	//采用类指针的方式复制字符串
		*(b+i) = *(a+i);
	*(b+i) = '';
	
	printf("字符串a为:%sn", a);
	printf("字符串b为:%sn", b);
	
	return 0;
}
例8.19复制字符串(使用指针变量)

同例8.18

#include
int main()
{
	char a[] = "I am boy.", b[20], *p1, *p2;
	p1 = a;
	p2 = b;
	
	for(; *p1 !=''; p1++, p2++)
		*p2 = *p1;
	*p2 = '';
	printf("字符串a为:%sn", a);
	printf("字符串b为:%sn", b);
	
	return 0;
	
}
例8.20字符指针作函数参数(复制字符串)

用函数调用实现字符串复制

#include
int main()
{
	void copy_string(char from[], char to[]);
	char a[] = "I am a teacher.";
	char b[] = "You are a sutdent.";
	printf("字符串a的内容为:%sn字符串b的内容为:%sn", a, b);
	copy_string(a, b);
	printf("n字符串a的内容为:%sn字符串b的内容为:%sn", a, b);
	
	return 0;
}

void copy_string(char from[], char to[])
{
	int i;
	while(from[i] != '')
	{
		to[i] = from[i];
		i++;
	}
	to[i] = '';
}

#include
int main()
{
	void copy_string(char from[], char to[]);	//函数声明,
	char a[] = "I am a teacher.";
	char b[] = "You are a student.";
	char *from = a, *to = b;
	printf("字符串a的内容为:%sn字符串b的内容为:%sn", a, b);
	copy_string(from, to);		//将字符串from的内容复制到字符串to中
	printf("n字符串a的内容为:%sn字符串b的内容为:%sn", a, b);
	
	return 0;
}

void copy_string(char from[], char to[])	//输出两个字符串,将字符串from内容复制到字符串to中
{
	int i = 0;
	while(from[i] != '')
	{
		to[i] = from[i];
		i++;
	}
	to[i] = '';
}
例8.21改变指针变量的值
#include
int main()
{
	char *a = "I love China.n";
	
	a = a+7;
	
	printf("%sn", a);
	return 0;
}
例8.22通过指针调用函数

求整数a和b中的最大值

#include
int main()
{
	int max(int x, int y);
	int (*p)(int, int);
	int a, b, c;
	
	p = max;
	printf("请输入两个整数:n");
	scanf("%d%d", &a, &b);
	
	c = (*p)(a, b);
	printf("%d和%d中的较大值为:%dn", a, b, c);
	
	return 0;
	
}
int max(int x, int y)	
{
	int z;
	z = x>y ? x : y;
	
	return z;
}
例8.23通过指针调用函数

输入两个整数,然后让用户选择1或2,选1时调用max函数,输出二者中的最大值。选2时调用min函数,输出二者中的最小值。

#include
int main()
{
	int max(int, int);	//函数声明,输入两个整数求最大值
	int min(int, int);	//函数声明,输入两个整数求最小值
	int (*p)(int, int);	//指向函数的指针
	int a, b, c, n;
	
	printf("请输入两个整数:n");
	scanf("%d%d", &a, &b);
	printf("n请选择要进行的操作:n");
	printf("t1.求最大值。nt2.求最小值。n");
	scanf("%d", &n);
	
	if(n==1)	p = max;
	else if(n==2)	p = min;	//若n为1,将max函数的地址存入p中
	else  printf("请输入数字1或2。");	//若n为2,将min函数的地址存入p中
	c = (*p)(a,b);		//运行地址为p的函数
	
	if(n==1)
		printf("n最大值为:%d", c);
	else if(n==2)
		printf("n最小值为:%d", c);
	
	return 0;
	
}

int max(int x, int y)	//max函数,求输入两个数的最大值
{
	int z;
	if(x>y) z = x;
	else 	z = y;
	
	return z;
}

int min(int x, int y)	//min函数,求输入两个数的最小值
{
	int z;
	if(x>y)	z = y;
	else 	z = x;
	
	return z;
}

例8.24指向函数的指针

有两个整数a和b,由用户输入1,2或3.若输入1,程序就给出a和b中的最大值,输入2,程序就给出a和b中的最小值,输出3则求a与b的和。

#include
int main()
{
	void fun(int x, int y, int (*p)(int, int));	//fun函数声明
	int max(int, int);	//max函数声明
	int min(int, int);	//min函数声明
	int add(int, int);	//add函数声明
	int a, b, n;
	
	printf("请输入两个整数:");
	scanf("%d%d", &a, &b);
	printf("n请选择:n");
	printf("1.求最大值n2.求最小值n3.求和nn");
	scanf("%d", &n);
	
	if(n==1)	fun(a, b, max);
	else if(n==2) fun(a, b, min);
	else if(n==3) fun(a, b, add);
	
	return 0;
}

void fun(int x, int y, int (*p)(int ,int))
//fun函数,输入两个整数和所需的函数,输出函数运行结果
{
	int result;
	result = (*p)(x, y);
	printf("%dn", result);
		
}

int max(int x, int y)//max函数,输入两个整数,求最大值
{
	int z;
	if(x>y)	z = x;
	else 	z = y;
	
	printf("最大值为:");
	return z;
}

int min(int x, int y)	//min函数,输入两个整数,求最小值
{
	int z;
	if(x>y)	z = y;
	else  	z = x;
	
	printf("最小值为:");
	return z;
}

int add(int x, int y)//add函数,输入两个整数,求和
{
	int z;
	z = x+y;
	
	printf("两数的和为:");
	return z;
}

例8.25返回指针的函数

有a个学生,每个学生有b门课程的成绩。要求在用户输入学生序号以后,能输出该学生的全部成绩。

#include
int main()
{
	float *search(float (*pointer)[4], int n);	//函数声明
	float score[][4] = {{60,70,80,90},{56,89,67,88},{34,78,90,66}};
	float *p;
	int i, k;
	
	printf("请输入学生编号:");
	scanf("%d", &k);
	printf("n学生编号为%d的学生成绩为:n", k);
	
	p = search(score, k);
	for(i=0; i<4; i++)
		printf("%5.2ft", *(p+i));
	printf("n");
	
	return 0;
}

float *search(float (*pointer)[4], int n)	//float函数,输入一个数组和一个整数
{											//输出二维数组的列的第一个元素的地址
	float *pt;
	pt = *(pointer+n);
	return pt;
}
例8.26

对例8.25中的学生,找出其中有不及格的课程的学生及其学生号。

#include
int main()
{
	float score[][4] = {{60,70,80,90},{56,89,67,88},{34,78,90,66}};
	float *search(float (*pointer)[4]); //函数声明
	float *p;
	int i, j;
	
	for(i=0; i<3; i++)
	{
		p = search(score+i);
		if(p==*(score+i))
		{
			printf("学生%d:", i);
			for(j=0; j<4; j++)
				printf("%5.2f  ", *(p+j));
			printf("n");
		}
	}
	return 0;
}

float *search(float (*pointer)[4])	//search函数,输入一维数组,返回指针
{
	int i = 0;
	float *pt;
	
	pt = NULL;
	
	for(; i<4; i++)
		if(*(*pointer+i)<60)
			pt = *pointer;
	return pt;
}

例8.27指针数组

将若干字符串按字母顺序输出

#include
#include
int main()
{
	void sort(char *name[], int n);		//函数声明
	void print(char *name[], int n);	//函数声明
	char *name[] = {"Follow me","BASIC","Great Wall","FORTRAN","Computer design"};
	
	int n = 5;
	sort(name, n);		//调用sort函数,对字符串排序
	print(name, n);		//调用print函数,输出字符串
	
	return 0;
}

void sort(char *name[], int n)	//sort函数,对字符串排序
{
	char *temp;
	int i, j, k;
	
	for(i=0; i0)	//strcmp函数,是系统提供的字符串比较
				k = j;
		if(k!=i)
		{
			temp = name[i];
			name[i] = name[k];
			name[k] = temp;
		}
	}
}

void print(char *name[], int n)	//prnt函数,对输出字符串
{
	int i;
	for(i=0; i 
例8.28指向指针的指针变量 
#include
int 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("%sn", *p);
	}
	return 0;
}
例8.29
#include
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++);
	}
	printf("n");
	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/605056.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号