善于利用指针

本文详细介绍了C语言中的指针概念,包括直接访问与间接访问、指针变量的定义和引用、指针作为函数参数的使用、通过指针引用数组和多维数组、字符指针与字符数组的区别、指向函数的指针以及指针数组。通过多个例题演示了指针在实际编程中的应用,帮助读者掌握指针的使用技巧。
摘要由CSDN通过智能技术生成

指针

在程序中定义一个变量时,系统会为该变量创建一个存储单元。存储单元的编号被称为地址。程序可以通过地址找到变量,即地址指向变量,因此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=%f\n";
printf(format, a, b);

等价于

printf("a=%d,b=%d\n", a, b);

指向函数的指针

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

指向函数的指针的优势

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

返回指针值的函数

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

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

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

指针数组

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

例题汇总

例8.1初识指针

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

#include<stdio.h>
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=%d\n", 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<stdio.h>
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<b,交换两个指针变量的值。即p1指向较大的数,p2指向较小的数
	{
   
		p = p1;
		p1 = p2;
		p2 = p;
	}
	
	printf("a=%d,b=%d\n", a, b);	//if语句没有改变a与b的值
	printf("max=%d,min=%d\n", * p1, * p2);	//指针变量的指向改变了
	
	return 0;
}

例8.3指针变量函数

同例8.2

#include<stdio.h>
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("最大值为:%d\n最小值为:%d", a, b);
}

void swap(int *p1, int *p2)
{
   
	int temp;
	
	temp = *p1;		
	*p1 = *p2;
	*p2 = temp;
	
}
/*
若交换函数写成如下则不会实现交换的功能
void swap(int x, int y)
{
	int temp;

	temp = a;
	a = b;
	b = temp;
}
执行swap函数后,x和y的值互换了,但并未影响a和b的值。
这是由于函数是“单向传送”的“值传递”,形参的改变不会印象实参的值。

*/

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

同例8.2

#include<stdio.h>
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("最大值为:%d\n最小值为:%d", *pointer_1, *pointer_2);
	
	return 0;
}

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

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

例8.5

输入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("请输入3个整数:\n");
	scanf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值