900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > C语言关键字static与extern的详细解释

C语言关键字static与extern的详细解释

时间:2024-04-08 18:27:38

相关推荐

C语言关键字static与extern的详细解释

参考原文地址(static):/keyeagle/article/details/6708077

参考原文地址(extern):/Lunais/p/5991135.html

C语言中的static与extern是C语言32个关键字中的比较重要的两个内容,也是我近期在学习C++过程中理解较为晦涩的部分,为此,参考了一些优质资料,在此做个总结。

C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重复定义的话编译器就会报错。伴随着不同源文件变量和函数之间的相互引用以及相互独立的关系,产生了extern和static关键字。

修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。

一、static修饰全局变量

一个程序在内存中的布局:栈(局部变量,动态分配)、堆(用户自行申请、释放,通过指针访问)、bss段(存放进程中未初始化的全局变量)、data段(存放进程中初始化的全局变量)、text段(存放程序执行的二进制文件)、其他段(未知)。

静态全局变量:当进程中一个全局变量被static修饰后(被声明为static),则该全局变量被称为静态全局变量。

静态全局变量的存储位置不变,在bss段(未初始化)或者data段(初始化),但它的作用域是仅在它的源文件内,其它源文件都无法访问它。所以,当全局变量被static修饰后,就会限定在当前源文件(.c)内使用。

全局变量:隐式被static修饰的全局变量,作用域也是仅在它的源文件内,不能被其它源文件访问。但与静态全局变量(显式被static修饰的全局变量)不同的是全局变量在其它源文件中可以通过extern声明后访问,而静态全局变量则无法访问。

file1.h文件,声明printer函数

//file1.hvoid printer(void);

file1.c文件,定义了 静态全局变量name、全局变量address,以及printer函数

//file1.c#include <stdio.h>#include "file1.h"static char* name = "keke";char* address = "jiangxi";void printer(void){printf("%s\n",name);printf("%s\n",address);}

file2.c文件,可以成功调用printer函数,也可以通过extern声明访问全局变量address,但是无法访问name(即使被extern声明)

//file2.c#include <stdio.h>#include "file1.h"//extern char* name;extern char* address;int main(){printer();printf("%s\n",name);printf("%s\n",address);}

二、static修饰局部变量

局部变量可以被存放在栈(动态分配,每次调用,位置都可能不同,作用域是局部)、堆(申请内存,要记得释放,作用域可以是整个源文件)当中。

静态局部变量:局部变量被static修饰后,则称为静态局部变量。静态局部变量则被存放在data段内(定义时,如果用户没有初始化,编译器会自动将其初始化为0),而且整个进程周期中,只定义和初始化一次,每次调用局部函数时,静态局部变量都会维持最后一次修改的值,作用域是局部代码段。

file3.c文件,在函数printer内分别定义了普通局部变量(i)和静态局部变量(j)。

//file3.c#include <stdio.h>void printer(void){int i;static int j;printf("i:%d j:%d\n",i++,j++);}int main(){printer();printer();printer();printer();printer();}

file.c文件执行结果如下:

i:-1218204059 j:0i:-1218204058 j:1i:-1218204057 j:2i:-1218204056 j:3i:-1218204055 j:4

可见,普通局部变量(i)每次调用函数的访问的值都不一样,而且随机;静态局部变量,定义初始化为0,并每次访问都是上一次函数调用修改的值。

三、static修饰函数

static函数:被关键字static修饰的函数。static函数作用域是源文件,即其他源文件无法调用该函数,类似C++中的private函数。而对于普通函数而言,其他源文件只要添加了该函数的头文件(.h),其他源文件就可以调用该函数。

当你的程序中有很多个源文件的时候,你肯定会让某个源文件只提供一些外界需要的接口,其他的函数可能是为了实现这些接口而编写,这些其他的函数你可能并不希望被外界(非本源文件)所看到,这时候就可以用static修饰这些“其他的函数”。

file4.h文件,声明了普通函数(func1)和静态函数(func2)

/file4.hvoid func1(void);static void func2(void);

file4.c文件,定义了普通函数(func1)和静态函数(func2)

/file4.c#include <stdio.h>#include "file4.h"void func1(void){printf("普通函数\n");func2();}static void func2(void){printf("静态函数\n");}

file5.c文件,通过添加file4.h,可以调用func1(),但无法调用func2()。但是,func1()可以调用func2()。

//file5.c#include "file4.h"int main(){func1();//func2();}

可见,静态函数只能被它的源文件调用,而无法被其它源文件调用(即使添加了对应的头文件)。

而且,static函数可以很好地解决不同源文件中函数同名的问题,因为一个源文件对于其他源文件中的static函数是不可见的。

四、extern修饰变量的声明

extern声明变量:表明该变量在其他源文件里已经被定义,此处需要使用。extern声明的变量必须是在其他源文件内的非静态的全局变量(保证作用域不受限制,可以声明)。

举例在file1.h/file1.c/file2.c中。

五、extern修饰函数的声明

extern声明函数:表明该函数在其他源文件里已经被定义,此处需要使用。extern声明的变量必须是在其他源文件内的非静态的函数(保证作用域不受限制)。

那么我们有两种方式可以其他源文件内的非静态函数,一种是添加该函数声明头文件(加载该头文件的全部函数,编译较慢),另一种是使用extern修饰(调用哪个函数,就声明哪个函数,编译较快,效率较高)。

举例在file4.h/file4.c/file5.c中。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。