函数指针声明语法混乱
Function pointer declaration syntax confusion
我已经阅读并在谷歌上搜索了解码函数指针的左右规则。
例如:
int (*(*fun_one)(char *,double))[9][20];
是:fun_one 是指向期望函数 (char *,double) 和
返回指向 int 数组(大小 20)的数组(大小 9)的指针。
那么什么是
const char code[] = "\x31\xc0";
int main(){
((void(*)( ))code)();
}
"code 是 ?? 返回指向返回 void 的函数的指针...????? 外面的 ()"
之后呢?
我对这个一头雾水。
const char code[] = "\x31\xc0";
int main(){
((void(*)( ))code)();
}
这是它的工作原理。 code
变量将衰减到第一个元素 (\x31
) 的地址。
然后该地址将被转换为接受不确定参数且不返回任何内容的函数的地址。
这涵盖了整个 ((void(*)( ))code)
位,到此为止,您基本上已经构建了一个指向您的字符串的函数指针。
()
然后简单地调用你指向的函数。
如果你的目标是 Intel CPU,31 c0
反汇编为 xor eax, eax
但当它用完缓冲区末端时我并不期待太多的快乐,它是可能会崩溃。标记字符串末尾的 \x00
是 add
指令的第一位,但至于后面的内容,则无法保证。
在字符串的末尾添加 ret
指令 可能 更安全,但您可能必须检查生成的汇编代码以找出调用本身应该使用哪个 ret
。
那不是函数指针声明,它是函数指针cast和call .
暂时忽略转换,我们有 ((
sometype)code)()
— 也就是说,将 code
转换为某种类型(显然是函数指针)然后调用它。
演员表中的类型是什么?是 void (*)()
。换句话说,一个指向函数的指针 returns void
并且没有任何特别的东西(它实际上 可以 接受参数,这要归功于 C 的遗留,但在这个如果没有)。无进无出。
如果这是一个声明,*
之后就是名称所在的位置,但由于它是一个强制转换,类型是独立的,根本没有名称。
你很困惑,因为它不是一个函数指针声明,而是一个转换后跟一个函数调用。
(void (*)()) code
这会将 code
转换为指向函数的指针,该函数接受未指定数量的参数且不返回任何内容。
((void (*)()) code)
这是上面括号中的整个表达式;结果是一个函数指针。
(void (*)() code)();
这调用了函数指针"created"所指向的函数。
这实际上是在尝试调用在 code
中构造的一些机器代码 - 这里您省略了其余部分,但 31 c0 是通常的 xor eax,eax
。
我已经阅读并在谷歌上搜索了解码函数指针的左右规则。
例如:
int (*(*fun_one)(char *,double))[9][20];
是:fun_one 是指向期望函数 (char *,double) 和 返回指向 int 数组(大小 20)的数组(大小 9)的指针。
那么什么是
const char code[] = "\x31\xc0";
int main(){
((void(*)( ))code)();
}
"code 是 ?? 返回指向返回 void 的函数的指针...????? 外面的 ()"
之后呢?我对这个一头雾水。
const char code[] = "\x31\xc0";
int main(){
((void(*)( ))code)();
}
这是它的工作原理。 code
变量将衰减到第一个元素 (\x31
) 的地址。
然后该地址将被转换为接受不确定参数且不返回任何内容的函数的地址。
这涵盖了整个 ((void(*)( ))code)
位,到此为止,您基本上已经构建了一个指向您的字符串的函数指针。
()
然后简单地调用你指向的函数。
如果你的目标是 Intel CPU,31 c0
反汇编为 xor eax, eax
但当它用完缓冲区末端时我并不期待太多的快乐,它是可能会崩溃。标记字符串末尾的 \x00
是 add
指令的第一位,但至于后面的内容,则无法保证。
在字符串的末尾添加 ret
指令 可能 更安全,但您可能必须检查生成的汇编代码以找出调用本身应该使用哪个 ret
。
那不是函数指针声明,它是函数指针cast和call .
暂时忽略转换,我们有 ((
sometype)code)()
— 也就是说,将 code
转换为某种类型(显然是函数指针)然后调用它。
演员表中的类型是什么?是 void (*)()
。换句话说,一个指向函数的指针 returns void
并且没有任何特别的东西(它实际上 可以 接受参数,这要归功于 C 的遗留,但在这个如果没有)。无进无出。
如果这是一个声明,*
之后就是名称所在的位置,但由于它是一个强制转换,类型是独立的,根本没有名称。
你很困惑,因为它不是一个函数指针声明,而是一个转换后跟一个函数调用。
(void (*)()) code
这会将 code
转换为指向函数的指针,该函数接受未指定数量的参数且不返回任何内容。
((void (*)()) code)
这是上面括号中的整个表达式;结果是一个函数指针。
(void (*)() code)();
这调用了函数指针"created"所指向的函数。
这实际上是在尝试调用在 code
中构造的一些机器代码 - 这里您省略了其余部分,但 31 c0 是通常的 xor eax,eax
。