首页 文章

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

提问于
浏览
2

请考虑以下代码:

a.c

#include <stdio.h>
#include "b.h"

static int a = 41;

static void test(void){
    a++;
    printf("a: %d\n", a);
}

int main(void){
    set_callback(test);
    call();

    return 0;
}

b.c

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代码吗?它可以在不同的平台和编译器上运行吗?

2 回答

  • 2

    是的,这是完美的代码甚至是良好的代码 . 您的 test 回调不需要是全局的 .

    在进行任何会影响从外部调用它的优化之前,编译器负责确保不在转换单元外调用该函数 .

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

    因此,唯一的影响是目标文件不会导出 test 符号(这称为Internal Linkage) .

  • 1

    你写了,

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

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

    当作者调用 set_callback(test); 时,他知道他将静态方法传递给外部模块,并允许外部模块调用它 .

    关键是作者负责 test 方法以及它的去向 . 他没有阻止做任何事情,但他可以控制他的数据去向何处;并且他 chose 将它传递给局外人 .

相关问题