C语言中 Viod类型指针与函数指针问题
发布网友
发布时间:2024-09-26 05:00
我来回答
共3个回答
热心网友
时间:2024-10-06 02:19
先回答问题二:
函数指针成为void*之后,指向的函数类型的信息会丢失。
函数指针其实是函数的入口地址。
函数可以看成由3个东西决定:形参列表,返回值类型,以及入口地址。
前两者在函数指针成为void*之后会消失。
那么在考虑问题二,就好一点:
函数的参数在传递的时候是这样的:系统有一个叫做堆栈的数据结构,参数由调用方压入堆栈,由被调用方方弹出堆栈。返回值(!!!)也一样。
我实验了一下:
int get(int a,int b,int c)
{
return a+b;
}
void caller()
{
char (*p)(int,int) ;
void *q;
q=(void*)&get;
p=(char(*)(int,int))q;
printf("%s\n", (*p)( (int)'a' ,1) );
}
结果是异常退出……
但是,
int get(int c,int b,int a)
{
return a+b;
}
void caller()
{
int (*p)(int,int) ;
void *q;
q=(void*)&get;
p=(int(*)(int,int))q;
printf("%x\n", 'b' );
printf("%x\n", (*p)( (int)'a' ,1) );
}
int main()
{
caller();
return 0;
}
不会产生任何错误,可是结果不正确:
62
22ff59
神奇的是,下面这个代码竟然结果正确!!!!!!!!!!!!!
int get(int a)
{
return a+1;
}
void caller()
{
int (*p)(int,int) ;
void *q;
q=(void*)&get;
p=(int(*)(int,int))q;
printf("%x\n", 'b' );
printf("%x\n", (*p)( (int)'a' ,1) );
}
int main()
{
caller();
return 0;
}
结果:
62
62
-----------
原因是:堆栈里面不仅有传参操作的数据,还有其他重要数据,稍有不慎就可能破坏了他的结构。由于传参的参数是最后压栈的,所以多传一个少一个都还好,但是返回值可能就处于了一个危险地带。
无论怎样,结果不能总是对……
所以,编程时要注意这一点。
热心网友
时间:2024-10-06 02:19
答案可能因为编译器不同而不同,下面针对常见的编译器回答
问题一:参数不同时编译出错,返回类型不同时编译不出错,运行可能出错
问题二:函数内部不知道它指向的函数类型,报错是编译器报错
指向函数的Void指针,在强制类型转换成另一种参数不同的函数指针后,使用它会造成:参数不匹配的编译错误
热心网友
时间:2024-10-06 02:20
问题一:在使用时强制转换成函数参数不同的函数指针,会导致出错,返回类型指针不同也会出错,对吗?
编译器无法得知你传入的函数指针funp是什么类型,所以编译时不会出错,但是运行时如果无法转换会抛出错误停止运行。
问题二,上面例子中函数内部怎样得知指向的函数类型。
这个是靠约定的,并不能提前得知。所以万能指针是非类型安全的,要避免使用。这种设计也是不太好的。
热心网友
时间:2024-10-06 02:14
先回答问题二:
函数指针成为void*之后,指向的函数类型的信息会丢失。
函数指针其实是函数的入口地址。
函数可以看成由3个东西决定:形参列表,返回值类型,以及入口地址。
前两者在函数指针成为void*之后会消失。
那么在考虑问题二,就好一点:
函数的参数在传递的时候是这样的:系统有一个叫做堆栈的数据结构,参数由调用方压入堆栈,由被调用方方弹出堆栈。返回值(!!!)也一样。
我实验了一下:
int get(int a,int b,int c)
{
return a+b;
}
void caller()
{
char (*p)(int,int) ;
void *q;
q=(void*)&get;
p=(char(*)(int,int))q;
printf("%s\n", (*p)( (int)'a' ,1) );
}
结果是异常退出……
但是,
int get(int c,int b,int a)
{
return a+b;
}
void caller()
{
int (*p)(int,int) ;
void *q;
q=(void*)&get;
p=(int(*)(int,int))q;
printf("%x\n", 'b' );
printf("%x\n", (*p)( (int)'a' ,1) );
}
int main()
{
caller();
return 0;
}
不会产生任何错误,可是结果不正确:
62
22ff59
神奇的是,下面这个代码竟然结果正确!!!!!!!!!!!!!
int get(int a)
{
return a+1;
}
void caller()
{
int (*p)(int,int) ;
void *q;
q=(void*)&get;
p=(int(*)(int,int))q;
printf("%x\n", 'b' );
printf("%x\n", (*p)( (int)'a' ,1) );
}
int main()
{
caller();
return 0;
}
结果:
62
62
-----------
原因是:堆栈里面不仅有传参操作的数据,还有其他重要数据,稍有不慎就可能破坏了他的结构。由于传参的参数是最后压栈的,所以多传一个少一个都还好,但是返回值可能就处于了一个危险地带。
无论怎样,结果不能总是对……
所以,编程时要注意这一点。
热心网友
时间:2024-10-06 02:19
答案可能因为编译器不同而不同,下面针对常见的编译器回答
问题一:参数不同时编译出错,返回类型不同时编译不出错,运行可能出错
问题二:函数内部不知道它指向的函数类型,报错是编译器报错
指向函数的Void指针,在强制类型转换成另一种参数不同的函数指针后,使用它会造成:参数不匹配的编译错误
热心网友
时间:2024-10-06 02:22
问题一:在使用时强制转换成函数参数不同的函数指针,会导致出错,返回类型指针不同也会出错,对吗?
编译器无法得知你传入的函数指针funp是什么类型,所以编译时不会出错,但是运行时如果无法转换会抛出错误停止运行。
问题二,上面例子中函数内部怎样得知指向的函数类型。
这个是靠约定的,并不能提前得知。所以万能指针是非类型安全的,要避免使用。这种设计也是不太好的。