如何在C中实现“私有/限制”功能?

时间:2009-09-09 20:04:00

标签: c function function-pointers

在C采访中我被问到一个非常有趣的问题:如何以一种只能从特定g()函数调用它的方式实现函数f()。如果g()以外的函数试图调用f(),则会导致编译器错误。

首先,我可以用函数指针完成,但我可以在运行时接近阻塞调用。但我无法想到编译时策略。我甚至不知道使用ansi C是否可行。

有没有人有任何想法?

6 个答案:

答案 0 :(得分:38)

这是一种方式:

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

答案 1 :(得分:27)

将g()和f()放在同一个模块中,并将f()声明为static。 static关键字使f()仅可用于同一模块或源文件中的函数。

您可能还想提一下,在f()和g()模块中不允许使用其他方法,否则可以调用f()。

PS - 我真的认为Chris Lutz的答案实际上是最好的。它提到了这种方法,但也是一个巧妙的宏重命名,它适用于较少的环境条件(不需要专门用于这两个功能的模块文件)。

另请注意,使用宏,您可以执行以下操作:

#define f() f_should_not_be_called_by_anything_except_g

这将提供一个很好的错误消息,并且当用户键入f()时,自动完成程序(如Visual Studio)将显示该提示。

答案 2 :(得分:10)

您可以使用static关键字生成模块私有函数:

static void func(void)
{
    // ...
}

然后,func()只能由同一文件中定义的其他函数调用(技术上,相同的翻译单元#include包含其定义的其他函数指令仍然可以访问它)。据说func内部链接。所有其他功能(即没有static关键字)都被认为具有外部链接。

除此之外,不,没有办法使功能无法访问。您可以使用宏来更改函数的名称,但其他代码仍然可以使用适当的名称访问它。

答案 3 :(得分:8)

f()g()放在同一个源文件中,声明f()静态。

答案 4 :(得分:8)

GCC的一个选项是使用nested functions。虽然它不是标准的C,但它的效果非常好。

答案 5 :(得分:2)

只有偶然。

如果函数f()和g()都在同一个源文件中,并且文件中没有其他函数,并且g()永远不会将函数指针返回到f()给任何一个调用者,然后使f()静态完成工作。

如果其他函数必须出现在同一个源文件中,请将f()作为静态函数放在文件的底部,并且只有在它之后立即定义g()才能获得或多或少相同的效果 - 尽管如果你没有告诉编译器在“遗漏声明”上生成错误,其他函数可能会在警告时调用它。

#include <stdio.h>

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()。