函数指针
注:该汇编使用intel格式,及与AT&T相反的操作方式
0x01 指针无法区分数据还是代码
1. 我们知道c/c++之所以伟大是因为很多方面,其中就是因为指针可以操作内存中的任意数据,理论上只要是在内存中,都可以操控。
2. 那么指针可以指向操作码吗???这个就可以打开潘多拉的魔盒了。其实是可以的,而且还可以打印机器码,因为操作指令是存在内存中的,然而寄存器算是和cpu最紧密的了,但是也只是常数。直接给cpu计算的,所以汇编当中的一条指令都会被压缩成一串数字,其中包括cpu行为,需要做的动作,如 mov a,$5 0x0040D788: C7 05 34 7E 42 00 05 00 00 00 ---->如果有兴趣可以在文章最后看见延伸。
0x02 函数指针的使用
我们都知道,指针操作数据的例子,int *p = &a ,这是们写过很多次的代码,然后我们开始介绍指针使用__代码__
int func(int a)
{
return 1;
}
int (*p)(int) = func; //
0x03 函数指针实现类重载
直接附上代码–注意void intergal(double a, double b, double (*fun)(double, double)) 函数
#include "stdio.h"
#include "math.h"
//intergal(x^2)
double func1(double a , double b)
{
double sum = 0.0;
double length = 0.000001;
double x = a;
while(x < b)
{
sum += x*x*0.000001;
x+=0.000001;
}
return sum;
}
//intergal(sinx)
double func2(double a , double b)
{
double sum = 0.0;
double length = 0.000001;
double x = a;
while(x < b)
{
sum += sin(x)*0.000001;
x+=0.000001;
}
return sum;
}
//intergal(e^(x^-2))
double func3(double a , double b)
{
double sum = 0.0;
double length = 0.000001;
double x = a;
while(x < b)
{
sum += exp(sqrt(x))*0.000001;
x+=0.000001;
}
return sum;
}
void intergal(double a, double b, double (*fun)(double, double))
{
double result = 0.0;
result = (*fun)(a, b);
printf("%g\n", result);
}
void main()
{
printf("计算x^2在0~1上的定积分结果:");
integral(0.0, 1.0, func1);
printf("计算sinx在0~π上的定积分结果:");
integral(0.0, 3.141593, func2);
printf("计算e^(x^-2)在0~1上的定积分结果:");
integral(0.0, 1.0, func3);
}
//---------引自代码揭秘--------------//
void intergal(double a, double b, double (*fun)(double, double)) 该函数不就是类似于重载的的函数吗??一个函数名,传入参数不同实现不同的逻辑,只需要将功能放入被指向的函数
0x04 奇葩的语法 int ((*p)(int,int)[10])(int);
当初看到这个真的是想吐,足足看了我半个小时,查资料看相视的函数才解决
int (*p)(int) ----这个就不说了嗷,大家都会
//接下来开始变形
int *(*p)()() //声明一个函数指针,该函数返回值为一个函数,返回函数的返回值为int *
int (*(*p)()()) //声明一个函数指针,该函数返回值为一个指针,该指针指向一个函数,该函数的返回值为int
int (*(*p)()[10])() //明一个函数指针,该函数返回值为一个指针数组,数组里的每一个指针都指向一个函数,该函数的返回值为int
//终极版
int *(*(*p)(int,int)[10])(int); //声明一个函数指针,该函数有两个int型参数该返回值为一个指针,指向一个数组,该数组里的每一个元素都是一个指针,指向一个函数,参数为int,返回值为int*
昨天晚上看到这个差点把我气哭了,天呐,这哪是语法啊,给我的感觉就像是,只要语法合理它可以一直跑下去,然后函数里面调用函数,函数里面返回指针的那种,虽然没有应用场景
附上
好了,解决了今日问题,该说说我进一步理解指针与内存了,
现附上一张图片,注意看地址和操作码!!!
然后就会惊奇的发现 0xE1216F - 0xE12168 刚好等于 c7 45 F8 00 00 00 00 等于7
惊奇吧!!
所以此时指针这样做, int * p = (int *)0x00E12168 然后16进制打印,就会出现 c7 45 F8 00 00 00 00
ps:有时候真理一直都在,你看不见是因为你知识积累不够,当然也有可能是你想不到hahahahah~~