static函数的作用是在链接层面上的

2015-02-26 YongHao Hu 更多博文 » 博客 » GitHub »

原文链接 http://yonghaowu.github.io/2015/02/26/static_function/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


先摆干货,总结:static函数的作用是在链接层面上的。

之所以研究static函数是因为Wine里面很多helper函数都是在.h文件里声明为static, 其作用就是避免命名冲突。

1. 正如很多C语言书籍里都有提到:

函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。 定义静态函数的好处: 其他文件中可以定义相同名字的函数,不会发生冲突 静态函数不能被其他文件所用。

基于此,我做了两个测试。

1. A.h里直接有a函数,static b函数的定义,a函数调用了b函数。 然后B.c #include A.h, 调用a, 没有问题。
2. A.h里有a , static b函数的声明,A.c里才定义a和b函数,也是a函数调用了b函数。 然后B.c #include A.h, 调用a, 报错,在B.c中b函数是undefined reference

当出现这样的结果时,我以前对static函数的认知是例子2里的作用;而在1里,我认为static失去它原来的作用,变得可有可无,就是没有也是可以的。对此,我再举一个例子来说明:

> B.c文件里引用了A.h, A.h有一个定义了的haha()函数,haha函数就是一个在A.h里面其他函数的helper,声明了为static,不想被其他文件调用,出现命名冲突。 
但是B.c自己本身也定义了一个haha函数,那么就会有冲突了。那么static就起不到作用。

> 但如果是按照2的方式,声明与定义分开,就没有这个问题。我做过测试,是可以这样,调用的是B.c自己的haha, 而把static删去后,就会报错重定义。


后来QianHong点出了问题所在, 反驳了我“可有可无”的观点

> 在1的方式中
加入B.c 编译为 B.o, C.c 编译为 C.o
然后 B.o 和 C.o 再合起来链接为 ./binary
如果没有在A.h 对 b函数使用 static 关键字
那么 C.c (C.o) 里就不可以定义一个新的 b 函数
如果 A.h 对 b函数使用了 static 关键字
那么 C.c(C.o) 里就可以定义另一个 b 函数
C.c刻意不include A.h

可知,1中的static是在链接层面上的。而我们一般的理解则是2中的。
当变量或者函数被static关键字修饰后,导致它成为一个 LOCAL 的符号,所
以static 的作用是声明 符号为 LOCAL 的,不被链接器处理,
如果把多个目标文件链接在一起, LOCAL 的符号只能在某一个目标文件中定义和使用,而不能定
义在一个目标文件中却在另一个目标文件中使用。