第八章 善于利用指针

8.1 指针是什么

指针是一个地址,指针变量就是地址变量,用来存放地址,指针变量的值是地址(即指针)。

8.2 指针变量

怎样定义指针变量

类型名 *指针变量名
如:int *pointer_1,*pointer_2;
可以在定义指针变量时,同时对它初始化
如:int *pointer_1=&a,*pointer_2=&b;

注意:
(1)指针变量前面的""表示该变量为指针型变量。变量名是pointer_1和pointer_2。
(2)在定义指针变量时必须指定基类型。一个指针变量只能指向同一个类型的变量。一个变量的指针的定义包括两个方面,一是以存储单元编号表示的纯地址(如编号为2000的字节),一是它指向的存储单元的数据类型(如int,float,char等)。
(3)指向整型数据的指针类型表示为"int
",读作"指向int的指针"或简称"int指针"。
(4)指针变量中只能存放地址(指针),不要将一个整数赋给一个指针变量。

怎样引用指针变量

  1. 给指针变量赋值。如:p=&a;
  2. 引用指针变量指向的变量。
    如:p=&a; printf("%d",*p);
    如果有:*p=1;表示将整数1赋给p当前所指向的变量,如果p指向变量a,相当于把1赋给a,即a=1;
  3. 引用指针变量的值。如:printf("%o",p);
    作用是以八进制数形式输出指针变量p的值,如果p指向了a,就是输出了a的地址,即&a。

输入a和b两个整数,按先大后小的顺序输出a和b。思路:交换两个指针变量的值。

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

指针变量作为函数参数

#include <stdio.h>
int main()
{void swap(int *pointer_1,int *pointer_2);
int a,b;
int *pointer_1,*pointer_2;
printf("Please enter two integer numbers:");
scanf("%d,%d",&a,&b);
p1=&a;
p2=&b;
if(a<b) swap(pointer_1,pointer_2);
printf("max=%d,min=%d\n",a,b);
return 0;
}

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

用指针变量作为函数参数,在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来, 这样就实现了"通过调用函数使变量的值发生变化,在主调函数(如main函数)中可以使用这些改变了的值"的目的。

如果想通过函数调用得到n个要改变的值:

  1. 在主调函数中设n个变量,用n个指针变量指向它们;
  2. 设计一个函数,有n个指针形参。在这个函数中改变这n个形参的值;
  3. 在主调函数中调用这个函数,在调用时将这n个指针变量作实参,将它们的值,也就是相关变量的地址传给该函数的形参;
  4. 在执行该函数的过程中,通过形参指针变量,改变它们所指向的n个变量的值;
  5. 主调函数中就可以使用这些改变了值的变量。

不可能通过执行调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。
函数的调用可以(而且只可以)得到一个返回值(即函数值),而使用指针变量作参数,可以得到多个变化了的值。

8.3 通过指针引用数组

数组元素的指针

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

p=&a[0];
p=a;//这两语句等价
//在定义指针变量时可以对它初始化
int *p=&a[0];
//等效于下面两行
int *p;
p=&a[0];
//也可以写成
int *p=a;
//将a数组首元素(即a[0])的地址赋给指针变量p

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

当指针指向数组元素时,可以对指针进行加和减的运算。
(1)如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。
(2)如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址。p+i↔a+i↔&a[i] 地址
(3)*(p+i)或*(a+i)是p+i和a+i所指向的数组元素,即a[i]。*(p+i)↔*(a+i)↔a[i] 元素
(4)如果指针变量p1和p2都指向同一数组中的元素,如执行p2-p1,结果是p2-p1的值(两个地址之差)除以数组元素的长度。两个地址不能相加,无实际意义。

通过指针引用数组元素

引用一个数组元素:
(1)下标法,如a[i]形式
(2)指针法,如*(a+i)或*(p+i)
引用数组各元素:
(1)下标法(2)通过数组名计算数组元素地址,找出元素的值(3)用指针变量指向数组元素

注意:
(1)用指针变量p来指向元素,用p++使p的值不断改变从而指向不同的元素。

用数组名a变化的方法(a++)是不行的。因为数组名a代表数组首元素的地址,它是一个指针型常量,它的值在程序运行期间是固定不变的。

(2)要注意指针变量的当前值。
通过指针变量输出整型数组a的10个元素。

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

用数组名作函数参数
在这里插入图片描述如果有一个实参数组,要想在函数中改变此数组中的元素的值,实参与形参的对应关系有四种情况:

  1. 形参和实参都用数组名
  2. 实参用数组名,形参用指针变量
  3. 实参形参都用指针变量
  4. 实参为指针变量,形参为数组名

通过指针引用多维数组
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

8.4 通过指针引用字符串

字符串的引用方式

(1)用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符,也可以通过数组名和格式声明"%s"输出该字符串。

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

(2)用字符指针变量指向一个字符串常量,通过字符指针变量引用该字符串常量。

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

说明:
C语言中只有字符变量,没有字符串变量。
只是把"I love China!"的第一个字符的地址赋给指针变量string。
通过字符数组名或字符指针变量可以输出一个字符串,而对一个数值型数组,是不能企图用数组名输出它的全部元素的,只能逐个输出,否则输出结果是数组首元素的地址。

char *string="I love China!";
//等价于
char *string;
string="I love China!";

使用字符指针变量和字符数组的比较
(1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),绝不是将字符串放到字符指针变量中。
(2)赋值方式。可以对字符指针变量赋值,但不能对数组名赋值。

char *a;
a="I love China!";//将首元素地址赋给a
//不能对数组名赋值
char str[14];
str[0]=‘I’;//合法,对字符数组元素赋值
str="I love China!";//非法,数组名是地址,是常量,不能被赋值

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

char *a="I love China!";
//等价于
char *a;
a="I love China!";
//而对数组的初始化:
char str[14]="I love China!";
//不等价于
char str[14];
str[]="I love China!";//错误

(4)存储单元的内容。编译时为字符数组分配若干个存储单元,以存放各元素的值,而对字符指针变量只分配一个存储单元。定义字符数组时应及时把一个字符变量的地址赋给它。
(5)指针变量的值是可以改变的,而字符数组名代表一个固定的值(数组首元素的地址),不能改变。
(6)字符数组中各元素的值是可以改变的(可以对他们再赋值),但字符指针变量指向的字符串常量中的内容是不可以被取代的(不能对它们再赋值)。
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值