c语言 static与extern

内部函数和外部函数 
  函数一旦定义后就可被其它函数调用。 但当一个源程序由多个源文件组成时,在一个源文件中定义的函数能否被其它源文件中的函数调用呢?为此,C语言又把函数分为两类: 
一、内部函数 
  如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序其它文件中的函数调用,这种函数称为内部函数。定义内部函数的一般形式是:

static 类型说明符 函数名(形参表)   

内部函数也称为静态函数。但此处静态static的含义已不是指存储方式,而是指对函数的调用范围只局限于本文件。因此在不同的源文件中定义同名的静态函数不会引起混淆,但通过#include可以使用。

C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。
1)先来介绍它的第一条也是最重要的一条:隐藏。如果加了static,就会对其它源文件隐藏。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。
2static的第二个作用是保持变量内容的持久。存储在静态数据区的变量(无论是函数内or函数外部)会在程序刚开始运行时就完成初始化,也是唯一的一次初始化,函数内部的数据不会在函数结束时就消失,而是一直到程序结束。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的
3static的第三个作用是默认初始化为0。其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。

二、外部函数 
  外部函数在整个源程序中都有效,其定义的一般形式为: 

extern 类型说明符 函数名(形参表)   

如在函数定义中没有说明externstatic则隐含为extern。在一个源文件的函数中调用其它源文件中定义的外部函数时,应用extern说明被调函数为外部函数。函数的声明extern关键词是可有可无的,因为函数本身不加修饰的话就是extern的。而全局变量在外部使用声明时,extern关键词是必须的,如果变量无extern修饰且没有显式的初始化,则成为变量的定义,因此此时必须加extern,而编译器在此标记存储空间在执行时加载如内存并初始化为0。而局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈部分分配内存。

在声明的时候,extern居然可以被省略,所以会让你搞不清楚到底是声明还是定义,下面分变量和函数两类来说:

1)变量

尤其是对于变量来说。
extern int a;//声明一个全局变量a
int a; //定义一个全局变量a


extern int a =0 ;//定义一个全局变量a 并给初值。
int a =0;//定义一个全局变量a,并给初值,
第四个 等于 第三个,都是定义一个可以被外部使用的全局变量,并给初值。
不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。当你要引用一个全局变量的时候,你就要声明,extern int a;这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。

(2)函数
对于函数也一样,也是定义和声明,定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。 但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体,所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行两者如此不同,所以省略了extern也不会有问题。但是:虽然知道某个函数的声明,就可以调用这个函数,编译就能成功。不过想要这个程序能够运行成功,必须保证在链接的时候能找到函数的定义

#include<stdio.h>

void fun();

int main()

{

fun();

}//即使没有定义fun(),编译也可以通过 

通常全局变量的声明extern type data;和函数的声明会放在头文件.h里,然后使用时结合include功能。
总结下对变量而言,如果你想在本源文件中使用另一个源文件的变量,就需要在使用前用extern声明该变量,或者在头文件中用extern声明该变量;

对函数而言,如果你想在本源文件中使用另一个源文件的函数,就需要在使用前用声明该变量,声明函数加不加extern都没关系,所以在头文件中函数可以不用加extern。

声明(Declaration)用于说明每个标识符的含义,而并不需要为每个标识符预存储空间。预留存储空间的声明称为定义(Definition)。变量的声明有两种情况: 一种是需要建立存储空间的。
   例如:int a; 在声明的时候就已经建立了存储空间。 

另一种是不需要建立存储空间。
   例如:extern int a; 其中 变量a是在别的文件中定义的。 
  谨记:声明可以多次,定义只能一次。

C里面,所谓 static ,只是限制在当前源文件————这个只是对于编译器/链接器而言。但实际上,运行时,static和普通的extern 的函数/变量,没有区别。
例如:使用函数指针/变量指针,完全可以访问其他文件的 static 变量/函数
file01.h
int * iptr01;
typedef void (* funcPtr)(void);
funcPtr pfun01;
----------------------------

file01.c
#include "file01.h"
static int ivar01 = 36;
int * iptr01 = &ivar01;

static void hwfun (void);
funcPtr pfun01 = &hwfun;

void hwfun (void)
{
printf("hello world\n");
}
-------------------------

file02.c
#include "file01.h"
............
//在某个代码内
*iptr01 = 72;
//file01.c 中的ivar01  变为72;
pfun01();
//调用了file01.c 中的hwfun ,打印出hello world

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值