Chinaunix首页 | 论坛 | 博客
  • 博客访问: 818157
  • 博文数量: 756
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:40
文章分类

全部博文(756)

文章存档

2011年(1)

2008年(755)

我的朋友

分类:

2008-10-13 16:14:26

好久不写blog,不是我偷懒,而是确实没有什么可写的。一是,现在做的工作专业性太强,大部分时间又是在分析第三方公司提供OS、module的代码,做相关的集成(intergration),丝毫没有什么可以抽象出来和大家共同分享的心得和知识;二是,由于考虑到商业机密,很多东西是不能说不能提的,即便是偶们自己,带出公司外也是不允许的,所以只能把东西研究透,然后烂到肚子里。:)
(注:上述有些不实之处就是,偶可以传授给偶徒弟,不过也是传内不传外了^_^)

好了,言规正传,谈谈函数的声明和定义。虽然都是些老掉牙的知识,各个业界大佬的红宝书、白皮书也都有详细的阐述,但是偶发现很多人,包括偶的一些大牛的同事,还是没有理解清楚这些概念。所以偶也就在这里现现宝,老生常谈,充充偶的blog的面子了。

最早的C是没有声明的,只有定义,声明主要是提供给连接器(link)用的,现在好像C编译器也用到声明。(这句话我不太确定,你当作耳旁风好了)
定义就是给出一个函数的明确功能,比如:
int foo()
{
  
int i;
  
return i * i; 
}

在一个C的工程中,不允许出现同名的函数,说得更清楚点就是,一个函数只有一个定义(define)。这样做很容易理解,比如有两个不同实现的foo()函数,那么再某个调用的foo()的地方究竟应该跳转到何处呢?不得不说的是:ANSI C规定同一个C工程中一个函数只能有一个定义。(C++允许函数重载不在此讨论范围内)但是某些具体的C编译器允许一个函数在同一个工程的不同模块中有相同的定义,当然搂虽然内容相同的定义影响不大,但是...ANSI做事总不会错!^_^

声明(declare)是什么?声明就是告诉C编译器这儿有个函数,已经定义了。声明之后的代码就可以根据声明提供的信息去调用这个函数。声明的写法如下:
int foo();

extern int foo();

一般来说,在一个C文件里面,我们会把声明写在所有函数定义的上头,这样所有的函数定义中就可以用这些函数了,而不必考虑每个函数定义书写顺序。
//declare foo() and bar()
void foo();
void bar();

//define foo()
void foo()
{
  bar(); 
//As declare bar() before, so foo()can call bar()
}


void bar()
{
  
//do some thing
}

如果没有开头的bar()的声明,那么在foo()中调用bar()就是不允许的,因为foo()找不到bar()。

当然更规矩的写法是,是把declare写到与.c同名的head file里面,一般是.h, 在.c里面写对应函数的define。

如果bar()函数在我们的模块根本没有实现,bar()是由第三方提供的,我们要用 bar()的功能,但是我们目前还没有拿到bar()的代码,怎么办?用extern就可以搞定。
//declare extern function
extern void bar();

//declare function
void foo();

//define function 
void foo()
{
  bar(); 
//no problem to compile our module without define bar()
}

所以void bar() 和extern void bar()的区别就是:虽然两者都是全局(globle scope)的函数,但是如果没有extern 在编译的时侯势必要要求提供bar()的define,而加了extern之后就可以把查找bar的define的工作推迟到link的时侯进行。在link的时侯,会为extern的函数声明找到一个定义,如果出现了重复定义,或者定义和声明不一致,都会出现link错误。

值得一提的是,某些编译器把没加extern的函数声明也当作加了extern处理。

说到这里,顺便说说static了。static如果用作函数的定义,则说明当前函数的作用范围只在当前文件内,外面的文件看不到,编译成obj时也不会放在全局符号表里。当然,static也可以作为函数声明的限定语。他用来说明当前使用的这个函数,是在本文件中定义的。有个容易混淆的地方是:
//declare
static void bar();// 无论这里是用extern修饰,还是用static修饰,还是没有任何修饰,结果都一样
void foo();

//define 
void foo()
{
  bar(); 
//call bar() defined below
}


 static
void bar()
{
   
//do some thing
}
即便是外部定义了bar(),foo()调用也是本文件定义的bar()。因为在编译当前.c文件时,在本文件中已经找到了bar(),就没有必要再去外面找bar()的定义;只有在当前.c文件中找不到bar()的定义,才会去外面找bar()。

以上是我对这几个概念的理解,如有不足或者错误的地方,欢迎指正!

-------------
乾坤一笑 写于2005年6月11 日  转载请标明出处和原文链接

--------------------next---------------------

阅读(659) | 评论(0) | 转发(0) |
0

上一篇:C语言学习方法

下一篇:用Python处理CSV格式

给主人留下些什么吧!~~