指针二
一、通过指针引用多维数组
指针变量可以指向一维数组,也可以指向多维数组中的元素
1.多维数组元素的地址
二维数组:
例如:
int a[3][4]={{1,2,3,4},{9,11,13,15},{17,19,21,23}};
- a为二维数组名,a数组包含3行,即3个行元素:a[0],a[1],a[2]。
- 每一个行元素又是一个一维数组名,包含4个元素(即4个列元素):a[0]所代表的一维数组有4个元素:a[0][0]、a[0][1]、a[0][2]、a[0][3]
a代表二维数组首元素的地址,是由4个整形元素所组成的一维数组
a代表是首行(序号为0的行)的起始地址,a+1代表序号为1的行的起始地址
a[0]代表&a[0][0],a[1]代表&a[1][0]
a+1指向a[1],a+1的值是a[1]的起始地址
a[0]和*(a+0)等价,a[1]和*(a+1)等价,a[i]和*(a+i)等价
a[0]+1和*(a+0)+1都是&a[0][1],a[1]+2和*(a+1)+2都是&a[1][2]
a[i]+j和*(a+i)+j都是&a[i][j]
*(a[i]+j)和 *( *(a+i)+j)都是a[i][j]的值
*(a+i)和a[i]是等价的
a,a+i,a[i],*(a+i), *(a+i)+j,a[i]+j都是地址
*(a[i]+j)和 *( *(a+i)+j)是二维数组元素a[i][j]的值
2.指向多维数组元素的指针变量
- 指向数组元素的指针变量
- 指向由m个元素组成的一维数组的指针变量
一维数组有4个元素,因此p的基类型是一维数组,其长度是16字节
3.用指向数组的指针作函数参数
用指针变量作形参,以接受实参数组名传递来的地址
- 用指向变量的指针变量
- 用指向一维数组的指针变量
实参与形参如果是指针类型,应当注意他们的基类型必须一致
二、通过指针引用字符串
1.字符类型
字符指针char*
例:
int main()
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}
或者
int main()
{
const char* pstr = "hello bit.";
printf("%s\n", pstr);
return 0;
}
是把字符串 hello bit. 首字符的地址放到了pstr中。
2.字符串的引用方式
字符串是放在字符数组中
- 用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符,也可以通过数组名和格式声明“%s”输出该字符串
- 用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量
通过字符数组名或字符指针变量可以输出一个字符串,而对一个数值型数组,是不能企图用数组名输出它的全部元素
第二种方法:用指针变量访问字符串。通过改变指针变量的值使它指向字符串中的不同字符
3.字符指针做函数参数
字符数组名作参数,也可以用字符指针变量作参数
再被调用的函数中可以改变字符串的内容,在主调函数中可以引用改变后的字符串
函数的形参和实参可以分别用字符数组名或字符指针变量
调用函数时实参与形参的对应关系
实参 | 形参 | 实参 | 形参 |
---|---|---|---|
字符数组名 | 字符数组名 | 字符指针变量 | 字符指针变量 |
字符数组名 | 字符指针变量 | 字符指针变量 | 字符数组名 |
4.使用字符指针变量和字符数组的比较
用字符数组和字符指针变量都能实现字符串的存储和运算,但区别为:
- 字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址)而不是将字符串放在字符指针变量中
- 可以对字符指针变量赋值,但不能对数组名赋值
- 初始化的不同
- 字符指针变量赋初值:
char *a=“I love China!”;等价于 char *a;a=“I love China!”;- 数组的初始化
char str[14]=“I love China!”;- 数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值
- 编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元
- 指针变量的值是可以改变的,而字符数组名代表一个固定的值(数组首元素的地址),不能改变
- 字符数组中各元素的值是可以改变的(可以对他们再赋值),但字符指针变量指向的字符串常量中的内容是不可以被取代的(不能对他们再赋值)
- 引用数组元素
- 对字符数组可以用下标法(用数组名和下标)引用一个数组元素(如a[5]),也可以用地址法(如*(a+5))引用数组元素a[5]。
- 若定义了字符指针变量p,并使它指向数组a的首元素,则可以用指针变量带下标的形式引用数组元素(如p[5]),同样,可以用地址法(如*(p+5))引用数组元素a[5]
- 如果指针变量没有指向数组,则无法用p[5]或*(p+5)这样的形式引用数组中的元素
- 用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串
三、指向函数的指针
函数名就是函数的指针,代表函数的起始地点
指针变量指向函数:可以定义一个指向函数的指针变量,用来存放某一函数的起始地址
1.用函数指针变量调用函数
例如:
#include<stdio.h>
int main()
{
int max(int, int);
int(*p)(int, int);
int a, b, c;
p = max;
printf("请输入a和b:");
scanf("%d,%d", &a, &b);
c = (*p)(a, b);
printf("a=%d\nb=%d\nmax=%d\n", a, b, c);
return 0;
}
int max(int x, int y)
{
int z;
if (x > y)
z = x;
else
z = y;
return z;
}
结果:
请输入a和b:45,87
a=45
b=87
max=87
分析:
- int(*p)(int, int);用来定义p是一个指向函数的指针变量,最前面的int表示这个函数返回的值是整型的,后面括号中的两个int,表示这个函数有两个int型参数。
- 注意:*p两侧的括号不可省略,表示p先与 *结合,是指针变量,然后再与()结合,()表示的是函数,即该指针变量不是指向一般的变量,而是指向函数
- 若int *p(int, int);因为()优先级高于 *,它相当于int *(p(int, int));成为了声明一个p函数,这个函数的返回值是指向整型变量的指针
- p=max;的作用是将函数max的入口地址赋给指针变量p。函数名代表该函数的入口地址。调用的*p就是调用max函数
注意:p是指向函数的指针变量,他只能指向函数的入口处而不能指向函数中间的某一条指令处,因此不能用*(p+1)来表示函数的下一条指令
2.定义和使用指向函数的指针变量
定义指向函数的指针变量的一般形式为:
类型名(*指针变量名)(函数参数表列)
类型名是指函数返回值的类型
- 定义指向函数的指针变量,只能指向在定义时指定的类型函数。一个指针变量可以先后指向同类型的不同函数
- 如果要用指针调用函数,必须先使指针变量指向该函数
- 再给函数指针变量赋值时,只须给出函数名而不必给出参数
p=max(a,b)的作用是将调用max函数所得到的函数值赋给p
- 用函数指针变量调用函数时,只须将(*p)代替函数名即可(p为指针变量名),在(*p)之后的括号中根据需要写上实参
- 对指向函数的指针变量不能进行算术运算
- 用函数名调用函数,只能调用所指定的一个函数,而通过指针变量调用函数比较灵活,可以根据不同情况先后调用不同的函数
3.用指向函数的指针作函数参数
指向函数的指针变量的一个重要用途是把函数的入口地址作为参数传递到其他函数
指向函数的指针可以作为函数参数,把函数的入口地址传递给形参,能够在被调用的函数中使用实参函数
对作为实参的函数,应在主调函数中用函数原型作函数声明
四、返回指针值的函数
一般形式:
类型名*函数名(参数表列)
例如:有a个学生,每个学生有b门课程的成绩。要求在用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现
#include<stdio.h>
int main()
{
float score[][4] = { { 60, 70, 80, 90 }, { 56, 89, 67, 88 }, { 34, 78, 90, 66 } };
float *s(float(*ptr)[4], int n);
float *p;
int i, k;
printf("请输入学生的数量:");
scanf("%d", &k);
printf("第%d名分数是:\n", k);
p = s(score, k);
for (i = 0; i < 4; i++)
printf("%5.2f\t", *(p + i));
printf("\n");
return 0;
}
float *s(float(*ptr)[4], int n)
{
float *pt;
pt = *(ptr + n);
return pt;
}
结果:
请输入学生的数量:1
第1名分数是:
56.00 89.00 67.00 88.00
五、指针数组
指针数组是数组
指针数组是一个存放指针的数组
一般形式为:
类型名*数组名[数组长度];
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组
指向指针数据的指针变量
简称指向指针的指针
例如:有一个指针数组,其元素分别指向一个整型数组的元素,用指向指针数据的指针变量,输入整型数组各元素的值。
#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++;
}
printf("\n");
return 0;
}
结果:
1 3 5 7 9