C语言高级指针(1)

C语言的指针是C语言这门语言的精华所在,当然也是让很多人诟病的地方。
指针是什么?有这么一句话:“对于锤子来说,一切都是钉子。”那么换句话讲指针,即“对于指针来说,一切都是地址”。
内存是由一个个内存单元构成的,每个内存单元都有自己的地址。而指针就是用来存放这些地址的。凡是可以用指针来存储的变量,在指针看来它(变量)都是地址。
比如:
这里写图片描述
二级指针:
存放一个整型变量地址用一级指针来存放,int a=10; int* pa=&a; 指针变量也是变量,所以可以取的指针变量地址,存放一级指针变量地址用二级指针来存储。int *ppa=&pa .依次类推,存放二级指针变量地址用三级指针变量来存储。
对于指针来讲,重难点便是和其它知识的结合运用,如下:
指针数组:
指针数组,顾名思义,指针数组它是一个数组,数组元素类型是指针类型。
这里写图片描述
在main()函数的参数中便用了这种类型:
这里写图片描述
第一个是一个int型变量,表示参数的个数。
第二个是一个字符串指针数组,数组中的每一个指针都指向一个字符串,这些字符串就是用户传给程序的参数,这些参数用用空格分开。
第三个是环境变量。
数组指针:
数组指针不同于指针数组,两者强调的重点更是不同。前者强调此为指针,后者强调此为数组。数组指针是用来存放数组地址的指针变量。如:

int arr[10];
int (*parr)[10]=&arr;

这里写图片描述
那么在二维数组中,我们便可以用数组指针来接收二维数组,比如用在函数参数。

int a[3][3]={1,2,3,4,5,6,7,8,9};
int (*pa)[3]=a;

这里写图片描述
函数指针
函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。

double Add(double num1, double num2)
{
    return num1 + num2;
}
int main()
{
    double ret = 0.0;
    ret=Add(3.0, 5.0);
    printf("%lf", ret);
    system("pause");    
    return 0;
}

以上为用直接调用函数的方式来实现函数调用。
用函数指针方式来调用函数方法如下

double (*pAdd)(double num1, double num2)=&Add;
int main()
{
    double ret = 0.0;
    ret=(*pAdd)(3.0, 5.0);
    printf("%lf", ret);
    return 0;
}

对表达式 double (*pAdd)(double num1, double num2) 进行分析,依据运算符优先级顺序,这个声明有两个括号,第一个括号聚组作用,第二个括号函数调用作用,括号里面是它的参数。第一个括号迫使间接访问在函数调用之前进行,进行解引用后,是一个函数类型,所以pAdd是一个函数指针。
实际上,在函数调用时函数名首先被转换为一个函数指针,该指针指定函数在内存中的位置。然后,函数调用操作符调用该函数,执行开始于这个地址的代码。
所以调用函数可以用三种方法

//第一种
ret=Add(3,4);//直接用函数名称调用函数
//第二种
ret=(*pAdd)(3,4);//用函数指针来调用函数。这种方法并不是必须的,因为编译器在执行函数调用操作符之前又会把它转换回去。
//第三种
ret=pAdd(3,4);

函数指针数组
上面讲过指针数组的概念和意义,同样,函数指针数组可以理解为(函数指针 数组),有一个数组,数组的元素类型为函数地址。代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
double Add(double num1, double num2)
{
    return num1 + num2;
}
double Sub(double num1, double num2)
{
    return num1 - num2;
}
//double(*pAdd)(double num1, double num2) = &Add;//函数指针pAdd
//double(*pSub)(double num1, double num2) = &Sub;//函数指针pSub
double(*p[3])(double num1, double num2) = { Add, Sub };//函数指针数组
int main()
{
    double ret = 0.0;
    double result = 0.0;
    ret = p[0](3.0, 5.0);
    result = p[1](8.0, 2.0);
    printf("%lf\n", ret);
    printf("%lf\n", result);
    system("pause");
    return 0;
}

变量p是一个数组,数组大小为3,数组元素类型为函数类型。double(*p[3])(double num1, double num2)
可以用来实现转移表。
指向函数指针数组的指针
如上述中double(*parr[3])(double num1, double num2) 是一个函数指针数组,而函数指针数组的指针是一个指针,指向上面的表达式。
1,写出一个指针(*pparr)
2, 这个指针指向一个有三个元素的数组(*(*pparr)[3])
3,写出返回值和函数调用即完整的表达式为
double(*(*pparr)[3])(double num1, double num2)=&parr;
可以看到pparr是一个指针类型,这个指针指向一个含有三个元素的数组,每个元素是函数指针类型。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值