请考虑以下代码:
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 回答
是的,这是完美的代码甚至是良好的代码 . 您的
test
回调不需要是全局的 .在进行任何会影响从外部调用它的优化之前,编译器负责确保不在转换单元外调用该函数 .
如果它发现指向函数的指针被传递给外部函数,它必须避免对函数进行不兼容的优化 .
因此,唯一的影响是目标文件不会导出
test
符号(这称为Internal Linkage) .你写了,
如果作者不希望从另一个文件调用他的
test()
函数,他不应该将指针传递给外部模块!当作者调用
set_callback(test);
时,他知道他将静态方法传递给外部模块,并允许外部模块调用它 .关键是作者负责
test
方法以及它的去向 . 他没有阻止做任何事情,但他可以控制他的数据去向何处;并且他 chose 将它传递给局外人 .