【发布时间】:2011-01-12 01:27:38
【问题描述】:
用static 定义的函数是否有可能在文件范围之外被访问?
【问题讨论】:
-
如果你把函数放在头文件中。那么每个编译单元都会有一个静态版本。
用static 定义的函数是否有可能在文件范围之外被访问?
【问题讨论】:
这取决于您所说的“访问”是什么意思。当然,不能在任何其他文件中按名称调用该函数,因为它在另一个文件中是 static,但您有一个指向它的函数指针。
$ cat f1.c
/* static */
static int number(void)
{
return 42;
}
/* "global" pointer */
int (*pf)(void);
void initialize(void)
{
pf = number;
}
$ cat f2.c
#include <stdio.h>
extern int (*pf)(void);
extern void initialize(void);
int main(void)
{
initialize();
printf("%d\n", pf());
return 0;
}
$ gcc -ansi -pedantic -W -Wall f1.c f2.c
$ ./a.out
42
【讨论】:
可以通过函数指针从作用域外调用。
例如,如果您有:
static int transform(int x)
{
return x * 2;
}
typedef int (*FUNC_PTR)(int);
FUNC_PTR get_pointer(void)
{
return transform;
}
那么作用域外的函数可以调用get_pointer(),并使用返回的函数指针调用transform。
【讨论】:
不,除非编译器中存在错误。通常静态函数代码没有标记用于在目标文件中导出函数的名称,因此它不会呈现给链接器,也无法链接到它。
这当然只适用于按名称调用函数。同一文件中的其他代码可以获取函数地址并将其传递给另一个文件中的非静态函数,然后另一个文件中的函数可以调用您的静态函数。
【讨论】:
不能通过文件名在文件外部访问它。但是,您也可以将其分配给函数指针并在任何您想要的地方使用它。
【讨论】:
“访问”?这取决于你所说的这个词是什么意思。我假设当您说“静态函数”时,您谈论的是声明为 static 的独立函数(即使用内部链接声明),而不是 C++ 中的静态类成员函数,因为后者显然可以从任何地方轻松访问。
现在,声明为 static 的独立函数具有内部链接。它不能从任何其他翻译单元链接到。或者,换句话说,它不能被任何其他翻译单元按名称引用。如果这就是您所说的“从文件范围之外访问”的意思,那么不,它无法完成。
但是,如果其他翻译单元以某种方式获得指向该函数的指针(即,如果您以某种方式允许该指针“泄漏”到外部世界),那么任何人仍然可以通过进行 idirect 调用来调用该函数,因此“访问”它。例如,如果您声明
static void foo_static(void) {
}
extern void (*foo_ptr)(void) = foo_static;
然后在任何其他翻译单元中用户将能够做到
extern void (*foo_ptr)(void);
foo_ptr();
电话将转到您的foo_static 函数。我不知道这种访问是否符合您问题中的“访问”的条件。
【讨论】:
按照标准,静态函数不能在按名称文件范围之外访问,因为它受内部链接的约束。它的名称不会被导出,也不会提供给链接器。但是,它仍然可以像任何其他函数一样被函数指针访问和调用。
【讨论】:
只有诡计。该函数通常对链接器不可见,因此它不会让您这样做。
但是,如果您在同一编译单元(作为静态函数)内提供一个函数,该函数返回该函数的地址:
在main.c:
#inclde <stdio.h>
int (*getGet7(void))(void);
int main (void) {
int (*fn)(void) = getGet7();
printf ("Result is: %d\n", fn());
return 0;
}
在hidden.c:
static int get7 (void) {
return 7;
}
int (*getGet7(void)) (void) {
return get7;
}
这将导致调用静态函数get7。
pax> gcc -o demo main.c hidden.c ; ./demo
Result is: 7
【讨论】:
不,关键字 static 的目的是将函数名的范围限制在文件中。
【讨论】: