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

时间:2022-07-06 16:04:17

As far as I know, casting between incompatible function pointers, eg:

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

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

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

should never be done, as is 'undefined behaviour' according to the C standard.

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

However I can't see why, given the way function calls work in C, this example isn't safe. All I'm doing is disregarding an argument.

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

Assuming that the treatment of an int first argument is consistent, all that will happen is that the const char* will be placed in a register when doSomethingWithFn() calls aBinaryFunction, aUnaryFunction will run as expected, and the const char* may be overwritten during aUnaryFunction, but that's fine because nothing else will use it anyway.

假设int第一个参数的处理是一致的,所有会发生的是当doSomethingWithFn()调用aBinaryFunction时,const char *将被放置在寄存器中,aUnaryFunction将按预期运行,并且const char *可能会被覆盖aUnaryFunction,但这很好,因为无论如何没有其他人会使用它。

Am I missing something here, or is this in fact safe? (Or something in between the two, or both?)

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

3 个解决方案

#1


6  

The problem is that there isn't a single "way function calls work in C" - there's only the way that function calls work on a particular C implementation.

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

As a concrete example, "callee clean-up" calling conventions (like x86 stdcall) require the callee to know how many parameters were pushed on to the stack to perform the correct cleanup, which would be subverted in your example.

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

#2


5  

This boils down to calling conventions. What if arguments are "sent" in reverse order for example? Or if there's a standard procedure that must be done after the function call that relies on the right number of arguments?

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

What you propose might work, but you shouldn't rely on this and the Standard attributes this as undefined behavior for a reason.

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

#3


0  

By the way, 'undefined behavior' is secret code for "don't do it, it's NOT safe!".

顺便说一句,“未定义的行为”是“不要做它,它不安全!”的密码。

It indicates that it won't work on different machines or even different versions of the same compiler on the same machine.

它表明它不能在同一台机器上的不同机器上工作,甚至不能在同一编译器的不同版本上工作。

#1


6  

The problem is that there isn't a single "way function calls work in C" - there's only the way that function calls work on a particular C implementation.

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

As a concrete example, "callee clean-up" calling conventions (like x86 stdcall) require the callee to know how many parameters were pushed on to the stack to perform the correct cleanup, which would be subverted in your example.

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

#2


5  

This boils down to calling conventions. What if arguments are "sent" in reverse order for example? Or if there's a standard procedure that must be done after the function call that relies on the right number of arguments?

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

What you propose might work, but you shouldn't rely on this and the Standard attributes this as undefined behavior for a reason.

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

#3


0  

By the way, 'undefined behavior' is secret code for "don't do it, it's NOT safe!".

顺便说一句,“未定义的行为”是“不要做它,它不安全!”的密码。

It indicates that it won't work on different machines or even different versions of the same compiler on the same machine.

它表明它不能在同一台机器上的不同机器上工作,甚至不能在同一编译器的不同版本上工作。