C功能指针 - 当您放弃参数时会发生什么?

时间:2011-03-27 01:34:57

标签: c function pointers signature arguments

所有。我目前正在使用一个旧的已建立的代码库来完成一个基本上没有文档记录的新项目(即每个文件平均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参数的定义短一个参数。

3 个答案:

答案 0 :(得分:3)

正式地,结果是未定义的:如果类型匹配,则只允许通过函数指针调用函数。

至于实际发生的事情,它取决于调用约定以及函数对参数的作用。机会是,结果不会很好。

答案 1 :(得分:3)

加上詹姆斯的回答:

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

虽然将passedFunction上的通话约定更改为stdcall,但您正在进行一些烟花爆竹。

答案 2 :(得分:2)

从下面的示例代码中,似乎在检查期间函数指针中定义的变量不重要。下面的代码在没有警告的情况下编译。

#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()中的变量将是垃圾。