C 函数指针 - 删除参数时会发生什么?

发布于 2024-10-27 03:13:49 字数 829 浏览 4 评论 0原文

全部。我目前正在为一个新项目使用一个旧的已建立的代码库,该项目基本上没有文档记录(即每个文件平均有 1 个单行注释)。我刚刚遇到了一些我以前从未见过的东西,并且不太确定如何解释。

首先,他们在头文件(.h)中定义了一个函数类型和一个函数,格式为:


typedef void (*SOME_FUNCTION)(void *data, EXECUTION_CONTEXT *ec);
void add_function(SOME_FUNCTION aFunction, void *data);

在主源文件(.c)中,定义了一个函数:


void add_function(void (*f)(void *data), void *data) 
{
   (Some code here)
}

好吧,有一个函数指针...但是什么第二个参数到底发生了什么,ec?为什么有人会使用这样的代码设计?作为参考,当使用函数 add_function 时,它以这种形式使用:


void passedFunction(void *data, EXECUTION_CONTEXT *ec) 
{
    (Stuff the function does.)
}

void CallingFunction()
{
    data = (some data stuff);
    add_function((SOME_FUNCTION)passedFunction, data);
}

因此,正如您所看到的,传递的函数使用适合原始 SOME_FUNCTION 参数签名的正确形式,但 add_function 参数的定义很短通过一个论点。

all. I'm currently working with an old established code base for a new project which is basically undocumented (i.e. averages 1 one-line comment per file). I just ran into something which I haven't seen before and am not quite sure how to interpret.

Firstly, they define a function type and a function in the header file (.h) in the form:


typedef void (*SOME_FUNCTION)(void *data, EXECUTION_CONTEXT *ec);
void add_function(SOME_FUNCTION aFunction, void *data);

In the main source file (.c), there is a function defined:


void add_function(void (*f)(void *data), void *data) 
{
   (Some code here)
}

So okay, there's a function pointer... but what the heck happened to the second argument, ec? Why would someone use a code design like this? For reference, when the function add_function is used, it is used in this sort of form:


void passedFunction(void *data, EXECUTION_CONTEXT *ec) 
{
    (Stuff the function does.)
}

void CallingFunction()
{
    data = (some data stuff);
    add_function((SOME_FUNCTION)passedFunction, data);
}

So, as you can see, the passed functions use the correct form that fits the original SOME_FUNCTION argument signature, but the definition for the add_function arguments is short by one argument.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

因为看清所以看轻 2024-11-03 03:13:49

形式上,结果是未定义的:如果类型匹配,则仅允许您通过函数指针调用函数。

至于实际发生的情况,取决于调用约定以及函数对参数的处理方式。很可能,结果不会好。

Formally, the results are undefined: you are only permitted to call a function via a function pointer if the types match.

As for what actually happens, it depends on the calling convention and what the function does with the arguments. Chances are, the results aren't going to be good.

谁的新欢旧爱 2024-11-03 03:13:49

添加詹姆斯的答案:

因为默认的调用约定很可能是 cdecl ,调用站点负责在 passedFunction 返回后清理堆栈。由于调用站点知道它只向被调用者传递了 1 个参数,因此编译器可以正常清理堆栈(即使从技术上讲这是未定义的行为)。

passedFunction 上的调用约定更改为 stdcall< /a> 不过,你会看到一些烟花。

To add on James' answer:

Since the default calling convention is most likely cdecl, the call site is responsible for cleaning up the stack after passedFunction returns. Since the call site knows that it passed just 1 argument to the callee, the compiler can clean up the stack normally (even though technically this is undefined behavior).

Change the calling convention on passedFunction to stdcall though, and you 're in for some fireworks.

少女七分熟 2024-11-03 03:13:49

从下面的示例代码来看,函数指针中定义的变量在检查过程中似乎并不重要。下面的代码编译时不会发出警告。

#include <stdio.h>

int temp(int (*m)());

int main(int argc, char *argv[]) {
        return temp(main);
}

int temp(int (*m)()) {
        return 1;
}

但是,下面的代码会引发错误。

#include <stdio.h>

int temp(void (*m)());

int main(int argc, char *argv[]) {
        return temp(main);
}

int temp(void (*m)()) {
        return 1;
}

由于这个原因;似乎编译器(至少在我的例子中是 GCC)只关心函数指针的返回值是什么。这里有趣的是,您可以正确发送参数,但如果您不指定参数(在我们的示例 m() 中),那么调用 m() 中的变量将是垃圾。

From the example code below, it doesn't appear that the variable(s) that are defined in the function pointer matters during the check. The code below compiles without warning.

#include <stdio.h>

int temp(int (*m)());

int main(int argc, char *argv[]) {
        return temp(main);
}

int temp(int (*m)()) {
        return 1;
}

However, the code below throws an error.

#include <stdio.h>

int temp(void (*m)());

int main(int argc, char *argv[]) {
        return temp(main);
}

int temp(void (*m)()) {
        return 1;
}

Due to this; it seems that the compiler (at least in my case GCC) only cares what the return value of the function pointer will be. The interesting thing here is that you CAN send the parameters correctly but if you do NOT specify the parameter (in our example m()), then the variables in m() when called will be junk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文