一、extern与函数
如果一个程序由多个源文件,编译成功后会生成对应的多个目标文件,这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如:a.obj文件可能会调用c.obj中定义的一个函数。将这些相关的目标文件链接在一起后生成可执行文件
1.外部函数和内部函数
1)外部函数:如果在当前文件中定义的函数允许在其它文件访问、调用,就称为“外部函数”。C语言规定,不允许有同名的外部函数。
2)内部函数:如果在当前文件中定义的函数只能在内部使用,就称为“内部函数”。C语言对顶不同的源文件可以有同名的内部函数,并不互相干扰。
2.外部函数
因为所有的函数默认就是外部函数,所以extern关键字和auto一样,就是废的。
常见的做法:
①创建one.c文件,在里面定义一些函数。
②创建one.h文件,在里面对one.c定义的函数进行声明。
③在main.c文件中,包含one.h头文件即可使用里面的函数。
3.外部函数使用例子
one.c
#include <stdio.h> void one(){ printf("this is method one()\n"); } void two(){ printf("this is method two()\n"); } void three(){ printf("this is method three()\n"); }
one.h
#ifndef __C__one_h #define __C_one_h void one(); void two(); void three(); #endif
first.c
#include <stdio.h> #include "one.h" int main(){ one(); two(); three(); return 0; }
执行指令:
gcc -c first.c one.c
gcc first.o one.o -o first.exe
first.exe
执行结果:
二、static与函数
1.定义内部函数
从上面的例子看出,one.c中定义的函数时可以被其他源文件访问的。其实有时候,我们想定义一个“内部函数”,不能被其他源文件访问的函数。只需使用static关键字修饰函数即可。
备注:
1)将上面的one函数用static关键字修饰一下,发现在链接的时候报错。
2)在编译阶段:编译器只检测单个源文件的语法是否不合理,并不测函数有没有定义;只有在链接的时候才会检测这个函数存不存在,也就是有没有被定义。
3)所谓编译:
就是单独检查每个源文件的语法是否合理,并不检查每个源文件之间的关联关系,一个源文件编译成功后就会生成一个目标文件。
所谓链接:就是检查目标文件的关联关系,将相关联的目标文件组合在一起,生成可执行文件。
2.声明和定义内部函数
#include <stdio.h> static void test(); int main(int argc, const char * argv[]) { test(); return 0; } static void test() { printf("调用了test函数"); }
三、static 、extern与函数的总结
1.static
在定义函数时,用static关键字进行修饰。内部函数又称为“静态函数”。这样该函数只能够在其定义的文件中使用,如果在不同的文件中有同名的外部函数,则互不干扰。
2.extern
使用extern关键字修饰的函数,就是外部函数,可以省略。默认定义的函数就是外部函数。
一个文件中想要调用其它文件中的外部函数,则需要再当前文件中使用extern声明该函数,然后就可使用,extern也可以省略。
四、static/extern与变量
1.全局变量的位置
在java中全局变量的位置是没有要求的。但是在C语言中,全局变量定义的位置是有限制的。默认一个函数不能访问在它后面定义的全局变量。
解决方法:
方法一:将全局变量定义到前面。
方法二:在前面用extern进行声明。
2.重复定义同一个变量
在C语言中,可以重复定义某个变量,它们始终代表的是同一个变量。
#include <stdio.h> int a=10; int main(){ extern int a; //表示引用全局变量,其实是多次一举,这行是多余的 a=12; //为全部变量重新赋值 printf("%d\n",a); return 0; } int a; //执行成功
#include <stdio.h> int a=10; //全局变量 int main(){ int a =12;//局部变量,和全部变量a之间没有任何关系 printf("%d\n",a); return 0; } int a;
3.不同源文件中的同名变量
在2个源文件中定义同一个变量,它们代表的都是同一个变量。
one.c
#include <stdio.h> int a; void one(){ printf("%d\n",a); }
first.c
#include <stdio.h> int a ; void one(); int main(){ a =12; one(); return 0; }
4.extern关键字
必须有已经声明过变量,才能使用extern关键字引用该变量。
例如:one.c中定义int a;在main.c中引用该变量,extern int a
但是不允许两边都使用extern修饰,因为都没定义,如何引用。
5.static
私有的全部变量:使用static关键字修饰的变量。该变量只能在该源文件内有效。
6.总结
1)extern可以用来引入一个全局变量。
2)默认情况下,一个变量是可以供多个源文件共享的,也就是说,多个源文件中同名的全局变量都代表着同一个变量。
3)如果在定义全局变量的时候加上static关键字,那么该全局变量仅限于定义该变量的源文件。与其它源文件中的同名变量互不干扰。