使用文件静态函数作为来自不同翻译单元的回调



请考虑以下代码:

交流电

#include <stdio.h>
#include "b.h"
static int a = 41;
static void test(void){
    a++;
    printf("a: %dn", a);
}
int main(void){
    set_callback(test);
    call();
    return 0;
}

不列颠哥伦比亚省

static void (*callback)(void);
void set_callback(void (*func)(void)){
    callback = func;
}
void call(void){
    if (callback){
        callback();
    }
}

B.H

void set_callback(void (*func)(void));
void call(void);

这将在没有警告-Wall的情况下进行编译,并按预期打印出a: 42

现在,这可能不是最佳实践,因为a.c的编写者可能不希望从另一个文件调用test()并且a修改变量,但这是合法的 C 代码吗?它会在不同的平台和编译器上移植吗?

是的,这是非常好的代码,甚至是好的代码。您的test回调不需要是全局的。

编译器负责确保不会在翻译单元外部调用函数,然后再执行任何会影响从外部调用函数的优化。

如果它看到指向函数的指针被传递给外部函数,则必须避免对函数进行不兼容的优化。

因此,唯一的效果是对象文件不会导出test符号(这称为内部链接)。

你写道,

现在,这可能不是最佳实践,因为 a.c 的编写者可能不希望从另一个文件调用 test() 并且变量是修改的,但这是合法的 C 代码吗?

如果编写器不希望从另一个文件调用他的test()函数,他不应该将指向它的指针传递给外部模块!

当编写者调用set_callback(test);时,他知道他正在将静态方法传递给外部模块,并授予该外部模块调用它的权限。

关键是作者负责test方法及其去向。 他没有被阻止做任何事情,但他可以控制他的数据的去向;他选择把它传给一个外人。

最新更新