将函数指针强制转换为接受更多参数的类型

Chr*_*eux 3 c casting function-pointers

据我所知,在不兼容的函数指针之间进行转换,例如:

void aUnaryFunction(int a1)
{
    /* .... */
}

void doSomethingWithFn()
{
    typedef void(*BinaryFn)(int, const char*);
    BinaryFn aBinaryFunction = (BinaryFn) &aUnaryFunction;
    aBinaryFunction (3, "!!!");
}
Run Code Online (Sandbox Code Playgroud)

永远不应该这样做,因为根据C标准,"未定义的行为".

但是我不明白为什么,假设函数调用在C中工作的方式,这个例子是不安全的.我所做的只是无视一个论点.

假设int第一个参数的处理是一致的,所有会发生的是const char*将在doSomethingWithFn()调用时放入寄存器中aBinaryFunction,aUnaryFunction将按预期运行,并且const char*可能会被覆盖aUnaryFunction,但这很好,因为无论如何,别的什么都不会用.

我在这里遗漏了什么,或者这实际上是安全的吗?(或两者之间,或两者兼而有之?)

caf*_*caf 6

问题是没有一个"方式函数调用C语言工作" - 只有函数调用在特定C实现上工作的方式.

作为一个具体的例子,"被调用者清理"调用约定(如x86 stdcall)要求被调用者知道有多少参数被推送到堆栈以执行正确的清理,这将在您的示例中被破坏.


sha*_*oth 5

这归结为呼叫约定.如果参数以相反的顺序"发送",例如怎么办?或者,如果在依赖正确数量的参数的函数调用之后必须执行标准过程?

您的建议可能有用,但您不应该依赖于此,并且标准将此属性定义为未定义的行为.