函数指针转换&探秘Tinycc什么不检查参数和返回值
本文将向你展示如何为函数赋值不同类型的参数及tinycc函数执行的过程
我们先看一下简单的函数指针转换
一个简单的函数如下,参数类型为int,我们能不能传一个字符串进去呢?
#include <iostream>
using namespace std;
void test2(int param) {
cout << param << endl;
}
测试:
int main()
{ //转换后该函数就可以接收一个字符串了
int(*func2)(string) = (int(*)(string))test2;
func2("10,ZXCVCX");
std::cout << "Hello World!\n";
}
再看一下下面这个转换,就会发现有意思的事情
#include <iostream>
using namespace std;
void test(int age,string name) {
cout << age << endl;
cout << name << endl;
return ;
}
class Student {
public:
int age;
string name;
};
int main()
{
void(*func)(Student) =(void(*)(Student))fun;
Student s1;
s1.age = 10;
s1.name = "ABC";
func(s1);
}
输出结果:
接下来我们就可以研究Tinycc做其它程序的c脚本时为什么不检查参数和返回值
假设我们有个函数如下
int test(int arg1,int arg2){
return arg1+arg2;
}
那么当我们使用tinycc提供的添加函数功能时
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
可以发现我们的函数test 从int()(int,int)类型转为了 const void类型 丢失了返回值和参数信息。
那么tinycc是怎么处理的呢,实际上tcc在解释执行时,再次将其转换为
void*()(…)类型。这样我们会发现一个问题,当我们的函数的返回值为double/float时由于无法从void转换为浮点类型,导致我们的函数无法获取正确的运行结果.
一个c++模拟的简单示例如下:
int myfun(int a,int b,int c) {
return a+b+c;
}
int main()
{
void* fun = (void*)test;
void*(*func)(...) =(void*(*)(...))myfun;
void* res = func(10,20,30);
int _b = reinterpret_cast<int>(res);
std::cout << _b << std::endl;
}