如何在C中实现“私有/受限”function?
在C采访中我被问到一个非常有趣的问题:如何以一种只能从特定的g()函数调用它的方式实现函数f()。 如果g()以外的函数试图调用f(),则会导致编译器错误。
起初,我虽然可以使用函数指针完成,但我可以在运行时接近阻塞调用。 但我无法想到编译时策略。 我甚至不知道使用ansi C是否可行。
有谁有想法吗?
这是一种方式:
int f_real_name(void) { ... } #define f f_real_name int g(void) { // call f() } #undef f // calling f() now won't work
另一种方法是,如果可以保证f()
和g()
是文件中唯一的函数,则将f()
声明为static
。
编辑:导致编译器错误的另一个宏技巧:
static int f(void) // static works for other files { ... } int g(void) { // call f() } #define f call function // f() certainly produces compiler errors here
将g()和f()放在同一个模块中,并将f()声明为static。 static关键字使f()仅可用于同一模块或源文件中的函数。
您可能还想提一下,在f()和g()模块中不允许使用其他方法,否则它们可以调用f()。
PS – 我真的认为Chris Lutz的答案实际上是最好的。 它提到了这种方法,但也是一个巧妙的宏重命名,它可以在较少的环境条件下工作(不需要专门用于这两个function的模块文件)。
另请注意,使用宏,您可以执行以下操作:
#define f() f_should_not_be_called_by_anything_except_g
这将提供一个很好的错误消息,并且自动完成程序(如Visual Studio)将在用户键入f()时显示提示。
您可以使用static
关键字创建模块专用函数:
static void func(void) { // ... }
然后, func()
只能由同一文件中定义的其他函数调用(技术上,相同的翻译单元 : #include
指令包含其定义的其他函数仍然可以访问它)。 据说func
有内部联系 。 所有其他函数(即没有static
关键字)都被称为具有外部链接。
除此之外,不,没有办法使function无法访问。 您可以使用宏来更改函数的名称,但其他代码仍然可以使用适当的名称访问它。
将f()
和g()
放在同一个源文件中,声明f()
静态。
GCC的一个选项是使用嵌套函数 。 虽然它不是标准的C,但它的效果非常好。
只有巧合才有可能。
如果函数f()和g()都在同一个源文件中,并且文件中没有其他函数,并且如果g()永远不会将函数指针返回到f()给任何调用者,那么使f ()static将完成这项工作。
如果其他函数必须出现在同一个源文件中,将f()作为静态函数放在文件的底部,并且只有在它之后立即定义g()会产生或多或少相同的效果 – 尽管如果你没有告诉编译器在“遗漏声明”上生成错误,其他函数可以通过警告调用它。
#include extern void g(void); /* in a header */ /* Other functions that may not call f() go here */ static void f(void) { puts("X"); } void g(void) { f(); }
显然,这种技术无法可靠地扩展到同一文件中的另一对函数 – x()和y() – 这样x()和x()可以调用y()而g()只有g()可以同时调用f()。
但是,通常你会依赖程序员的纪律,只需在源文件中生成f()静态,以及只有g()可以调用它的注释,然后训练修改代码的任何人,以便除了g()调用f()。