我想知道在这种情况下会发生什么:
int foo()
{
return 1;
}
void bar()
{
void(*fPtr)();
fPtr = (void(*)())foo;
fPtr();
}
将返回int的函数地址赋值给void(*)()类型的指针,并调用指向的函数。
- 标准对此有何规定?
- 无论第一个问题的答案如何:我们这样调用函数安全吗?实际上,结果不应该只是被调用者 (foo) 将某些内容放入 EAX/RAX 而调用者 (bar) 将忽略 rax 内容并继续执行程序吗?我对 Windows 调用约定 x86 和 x64 很感兴趣。
非常感谢您的宝贵时间
最佳答案
1) 来自 C11 标准 - 6.5.2.2 - 9
If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined
明确指出,如果使用与定义它的类型不匹配的类型的指针调用函数,则会导致未定义行为。 但是 Actor 还可以。
2) 关于你的第二个问题 - 如果调用约定 XXX 和实现 YYYY 定义明确 -
您可能已经反汇编了一个示例程序(即使是这个)并发现它“有效”。但是有轻微的并发症。你看,现在的编译器非常聪明。有一些编译器能够执行精确的过程间分析。某些编译器可能会发现您有未定义的行为,并且可能会做出一些可能会破坏该行为的假设。
一个简单的例子-
因为编译器发现这个函数是用 void(*)()
类型调用的,它会假设它不应该返回任何东西,它可能会删除返回所需的指令正确的值。
在这种情况下,调用此函数的其他函数(以正确的方式)将获得错误的值,因此会产生明显的不良影响。
PS:正如@PeterCordes 所指出的,任何现代、健全和有用的编译器都不会有这样的优化,使用这样的调用可能总是安全的。但答案和示例(可能过于简单)的目的是提醒人们在处理 UB 时必须非常小心。
关于c - 当您使用 void (*)() 指针调用返回 int 的函数时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47072443/