能够做到这一点:
struct foo { int (*bar)(void); char baz; };
然后有一个反向引用. C有一个名为cdecl的调用约定;基本上将参数推送到堆栈,有一个返回指针,然后跳转到某个地址.该地址的代码从堆栈中弹出参数并继续它的快乐方式.
thiscall约定略有不同,因为它隐式地添加了一个额外的参数,一个“this”指针.
因为你可以很容易地在C中开始执行任意字节代码并且由于gcc支持内联汇编程序模板化,这听起来像你可以制作一些宏以便你可以做类似的事情:
int bar(void) { GETTHIS; cThis->baz = 0; } int createFoo(struct Foo*pFoo) { ASSIGN(pFoo,bar); }
基本上ASSIGN会做的是回避cdecl来模仿一个thiscall样式约定,然后GETTHIS会做的是会计技巧的另一面.
我想知道是否:
>存在和解决方案
>如果没有,如果有一个原因导致无法完成
只有这一点;真正的“我们所有人都同意成年人”风格的会员功能,简直太棒了.谢谢!
笔记:
>我只是在谈论x86,linux,gcc ……我知道世界是一个广阔而陌生的地方.
>这纯粹是出于好奇.
解决方法
C has a calling convention called cdecl; basically pushes arguments on
to the stack,has a return pointer,then jumps to some address. The
code at that address pops arguments off the stack and goes on its
merry way.
被调用者不会从堆栈中弹出参数.它会读取参数而不会从堆栈中弹出它们.相反,堆栈由调用者清除.这是因为在cdecl约定中,被调用者不知道参数的确切数量.
现在,关于你的问题.没有严格定义的thiscall调用约定.更多信息here.
GCC-具体:
thiscall is almost identical to cdecl: the calling function cleans the
stack,and the parameters are passed in right-to-left order. The
difference is the addition of the this pointer,which is pushed onto
the stack last,as if it were the first parameter in the function
prototype
你无法隐藏额外的这个参数并在函数体内检索它,特别是因为这是第一个函数参数.如果隐藏它 – 所有其他功能参数将被移位.相反,你可以(并且应该恕我直言)将它声明为第一个函数参数,并且你可以直接访问它,而不需要额外的技巧:
int bar(struct foo *cThis) { cThis->baz = 0; }
MSVC特有的:
… the this pointer is passed in ECX and it is the callee that cleans
the stack,mirroring the stdcall convention used in C for this
compiler and in Windows API functions. When functions use a variable
number of arguments,it is the caller that cleans the stack (cf.
cdecl).
在这里,您可以通过将ECX寄存器的值复制到本地变量来实现技巧.像这样的东西:
#define GETTHIS \ struct foo *cThis; \ _asm { \ mov cThis,ecx \ };
然而,这很棘手,可能并不总是有效.原因是根据thiscall / stdcall调用约定,ECX寄存器保留用于函数,因此编译器可能生成覆盖ECX寄存器值的代码.这甚至可能在您调用GETTHIS宏之前发生.