gpt4 book ai didi

c++ - 是否可以显式调用名称损坏函数?

转载 作者:行者123 更新时间:2023-12-02 10:50:51 25 4
gpt4 key购买 nike

假设我有一些类似的东西

struct Foo {
void goo() {printf("Test");}
}

external void _ZN3Foo3gooEv(Foo *f);

int main() {
Foo f;
_ZN3Foo3gooEv(&f);
}
是否可以通过此处函数的名称错位版本调用 Foo::goo() ?
编辑:
澄清一下,这只是一个实验,看看是否可以显式调用名称重整函数。这里没有进一步的目标。
我被认为所有成员函数基本上都将 this 指针作为它们的第一个参数。
我知道这不会链接,但我不明白为什么。我认为名称重整发生在编译时,当链接器运行时,它会解析对名称重整函数的调用。 (这就是为什么我认为如果我们将 _ZN3Foo3gooEv 保留为 extern,它将去符号表查找它)。
我在这里误解了什么吗?

最佳答案

你可以,但有一些警告。
您要么必须以生成代码的方式使用成员函数,要么让它不是内联的,并且您的错误定义应该是 extern "C"以防止“双重破坏”。例如。:

#include <cstdio>

struct Foo {
const char* message;
void goo();
};

void Foo::goo() {
std::printf("%s", this->message);
}

extern "C" void _ZN3Foo3gooEv(Foo *f);

int main() {
Foo f{ "Test" };
_ZN3Foo3gooEv(&f);
}
可以正常工作并且特别是在 gcc 中稳定。
这是因为成员函数的调用约定等同于大多数系统上自由函数的默认调用约定。 this被传递给成员函数,就好像它是第一个参数一样,显式参数采用后面的 arg 传递槽。 (寄存器和/或堆栈)。我相信这对于 x86-64、至少 32 位和 64 位的 ARM 以及除 Windows 以外的 32 位 x86 都是正确的。
clang 似乎特别支持这个用例:它内联 Foo::goo进入 main当 gcc 假装 _ZN3Foo3gooEvFoo::goo在重整之后是两个独立的实体(因此不能被替换和内联)。
使用 MSVC,您可以执行类似的操作。但是,在 windows 上的 x86-32 代码中,调用约定 __thiscall 使用 where 而不是传递 this指针作为第一个参数,它与堆栈上的其他参数一起在 ECX 寄存器中传递。如果使用 clang 或 gcc 交叉编译 x86-32,您可以使用 [[gnu::thiscall]] ( __attribute__((thiscall)))。 ( fastcall 如果只有一个 arg 则类似,但有 2 个 args 将传递寄存器中的前 2 个,而不仅仅是第一个 1)。

但真的不应该有这样做的理由。它只能被视为编译器扩展(因为它使用 _Capital 符号),如果您需要从 C 中调用这些函数的方法,请使用帮助程序 void Foo_goo(struct Foo*)您在 C++ 翻译单元中定义的。它也可以调用私有(private)成员函数,但您已经可以通过模板特化以符合标准的方式执行此操作。

关于c++ - 是否可以显式调用名称损坏函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63948129/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com