2010-02-02 58 views
13

有没有可能在文件范围之外评估静态函数? ?其他文件中的静态函数访问

+7

如果你把函数放在头文件中。那么在每个编译单元中将会有一个静态版本。 – 2010-02-02 08:50:47

回答

19

这取决于你的意思是“访问”。当然,该函数不能在任何其他文件中被名称调用,因为它在不同的文件中是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 
12

不,除非编译器中有错误。通常情况下,静态函数代码没有标记为用于在目标文件中导出函数的名称,所以它不会显示给链接器,并且它不能链接到它。

这当然只适用于按名称调用函数。同一个文件中的其他代码可以获取函数地址并将其传递到另一个文件中的非静态函数中,然后来自另一个文件的函数可以调用您的静态函数。

4

遵循该标准,由于受到内部链接的限制,无法在文件的范围之外通过名称访问静态功能。它的名字没有被导出,也没有提供给链接器。但是,它仍然可以通过函数指针访问和调用,就像任何其他函数一样。

16

它可以通过函数指针从范围外调用。

例如,如果您有:

static int transform(int x) 
{ 
    return x * 2; 
} 

typedef int (*FUNC_PTR)(int); 

FUNC_PTR get_pointer(void) 
{ 
    return transform; 
} 

那么范围外的函数可以调用get_pointer(),并使用返回的函数指针调用转换。

+1

我认为应该是“int(* get_pointer(int))(void)”。 – paxdiablo 2010-02-02 11:26:49

+0

@paxdiablo和@caf - 谢谢。 – 2010-02-02 17:30:48

1

不,关键字static的目的是将函数名的范围限制到文件中。

6

它不能通过名称在文件外访问。但是,您也可以将其分配给函数指针并在任何需要的地方使用它。

3

只有诡计。该功能通常对链接器不可见,所以它不会让你这样做。

但是,如果你提供相同的编译单元内的函数(静态函数),它返回函数的地址:

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 
5

“Accessed”?这取决于你这个词的含义。我认为当你说“静态函数”时,你说的是独立函数,声明为static(即声明为内部链接),而不是C++中的静态类成员函数,因为后者在任何地方都可以很容易地访问。

现在,声明为static的独立函数具有内部链接。不能将从任何其他翻译单元链接到。或者,换句话说,它不能从任何其他翻译单位以名称来提及。如果这就是“从文件范围之外访问”的意思,那么不是,它不能完成。但是,如果其他翻译单元以某种方式获得指向该函数的指针(即,如果您以某种方式允许该指针“泄漏”到另一个世界中),那么任何人都仍然可以通过进行一个直接调用来调用该函数,从而“访问”它。例如,如果你声明

static void foo_static(void) { 
} 

extern void (*foo_ptr)(void) = foo_static; 

然后在任何其他翻译单元,用户将能够做到

extern void (*foo_ptr)(void); 
foo_ptr(); 

和呼叫转到您的foo_static功能。我不知道这种访问是否符合您的问题中的“访问”。