函数指针声明语法混淆

4
我已经阅读和搜索了关于使用右左规则解码函数指针的知识。
例如:
int (*(*fun_one)(char *,double))[9][20];

这段文本的翻译是:“fun_one是一个指向函数的指针,该函数期望(char *, double)类型的参数,并返回一个大小为9的int数组的数组(每个数组的大小为20)。所以,'所以什么呢?'”
const char code[] = "\x31\xc0";

int main(){
     ((void(*)( ))code)();
}

“code is ?? 返回指向返回void函数的指针...?? 然后()外面呢?”
我对这个非常困惑。

1
“frame” 是什么意思? - haccks
3个回答

3
const char code[] = "\x31\xc0";

int main(){
     ((void(*)( ))code)();
}

这是它的工作原理。 code 变量将降解为第一个元素 (\x31) 的地址。
然后,该地址将被强制转换为接受不确定参数并返回空值的函数的地址。
这涵盖了整个 ((void(*)( ))code) 位,到此为止,您基本上已经构建了指向字符串的函数指针。
然后,() 简单地调用您所指向的函数。
如果您要针对英特尔 CPU 进行操作,则 31 c0 的反汇编结果为 xor eax, eax,但当其运行超出缓冲区的末尾时,它很可能会崩溃。表示字符串结尾的 \x00 是一个 add 指令的第一部分,但关于其后面会出现什么,就没有保证了。
在字符串末尾添加一个 ret 指令可能会使其更安全,但您可能需要检查调用本身的生成汇编代码以找出应使用哪个 ret

2
你感到困惑是因为这不是函数指针声明,而是一个强制类型转换后跟随一个函数调用。
(void (*)()) code 

这将code转换为一个指向函数的指针,该函数接受未指定数量的参数并返回空值。
((void (*)()) code) 

这是整个表达式用括号括起来的结果,其返回一个函数指针。
(void (*)() code)();

这将调用由转换创建的函数指针所指向的函数。

这实际上是试图调用在code中构建的一些机器代码 - 在这里您省略了其余部分,但31 c0通常是xor eax,eax


哇,你不仅解释了,还解码了十六进制转储代码。太棒了。谢谢! - Haswell

2
那不是函数指针声明,而是函数指针的转换和调用。
暂时忽略转换,我们有 ((sometype)code)() — 即将 code 转换为某种类型(显然是函数指针),然后调用它。
那么转换中的类型是什么?它是 void (*)()。换句话说,它是指向返回 void 并且没有特定参数(实际上可以带参数,但在这种情况下没有)的函数的指针。没有输入,没有输出。
在 * 后面是名称,如果这是一个声明,但由于这是一个转换,类型独立存在,根本没有名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接