extern & static 在C语言中的用法

licalig 2006-03-02 01:32:35
好难理解这两个限定符。请大家指点指点。
这两个限定符有什么用途,用它们有什么好处?
先谢谢了!
...全文
1094 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
YUKIKING 2006-03-03
  • 打赏
  • 举报
回复
看看c语言书,不就知道了
licalig 2006-03-02
  • 打赏
  • 举报
回复
感谢河马!
谢谢大家了!
谢谢啊……^_^
cxc014 2006-03-02
  • 打赏
  • 举报
回复
幸好的我的是1280*1024是翻了6.4页.....
晨星 2006-03-02
  • 打赏
  • 举报
回复
不长不长,1024×768的分辩率下翻8页就看完了。。。。
dragonzxh 2006-03-02
  • 打赏
  • 举报
回复
长吗?还好啊~
duduhaha 2006-03-02
  • 打赏
  • 举报
回复
顶楼上的!呵呵.
楼主多google一下.
alen_ghl 2006-03-02
  • 打赏
  • 举报
回复
鄙视 河马
贴那么长贴,眼睛都看疼了!!!
jixingzhong 2006-03-02
  • 打赏
  • 举报
回复
好处:

extern 在大的工程中,不可能所有的内容在一个程序文件中,如果分割成多个文件,那么就不可能保证(一般情况下,特殊的不考虑)所有有调用关系的函数等在一个文件内,这个时候,就需要使用extern来外部申明,使函数等全局化。

static 对于变量来说,保存值是它的目的,防止重复的计算。
另外的功能就是局部的限制作用,在可能的情况下,一些意外的操作可能对一些数据产生影响,导致整个任务失败。而使用 static 限制就可以防止这中情况。
jixingzhong 2006-03-02
  • 打赏
  • 举报
回复
extern 全局化,和程序的其他部分共享变量等

static 本地化,禁止其他部分的访问,防止意外操作。
对于单个变量,还有保持静态的意思,让变量空间不释放,一直保存其内部的值
iamcaicainiao 2006-03-02
  • 打赏
  • 举报
回复
it's great. up all.
goodluckyxl 2006-03-02
  • 打赏
  • 举报
回复
static 作用只在文件内部,不具有外部联接
而extern与具有外部联接的内容产生关联
du51 2006-03-02
  • 打赏
  • 举报
回复
我觉得extern是为了跨文件域.
static是为了占满整个文件.
syd1207 2006-03-02
  • 打赏
  • 举报
回复
static 就是在本地声明了,只能在本地使用
extern 就是别的地方也声明
dragonzxh 2006-03-02
  • 打赏
  • 举报
回复
extern嘛就是一个声明.extern后面的已经在别的地方被声明过,
dragonzxh 2006-03-02
  • 打赏
  • 举报
回复
来本文只是本人对C++中关于静态类型的一个总结,如错误之处,请大家帮我改正。我分两个方面来总结,第一方面主要是相对于面向过程而言,即在这方面不涉及到类,第二方面相对于面向对象而言,主要说明static在类中的作用。
一、在面向过程设计中的static关键字
1、静态全局变量
定义:在全局变量前,加上关键字 static 该变量就被定义成为了一个静态全局变量(即全局静态变量)。全局静态变量使得该变量成为定义该变量的源文件所独享,也即静态变局变量对组成该程序的其他源文件是无效的。具体例子可见C++程序设计教程P103
特点:
  A、该变量在全局数据区分配内存。
  B、初始化:如果不显式初始化,那么将被隐式初始化为0。
  C、访变量只在本源文件可见,严格的讲应该为定义之处开始到本文件结束。
  例(摘于C++程序设计教程---钱能主编P103):
        //file1.cpp
        #include<iostream.h>
        void fn();
        extern int n;
        void main()
        {
          n=20;
          cout << n << endl;
          fn();
        }
        //file2.cpp
        #include<iostream.h>
        static int n; //定义静态全局变量,初始化为0;
        void fn()
        {
          n++;
          cout << n << endl;
        }
  文件分别编译能通过,但连接时file1.cpp 中的变量n找不到定义,产生连接错误。
使一个变量只在源文件中全局使用有时是必要的。
第一, 不必担心另外源文件使用它的名字,该名字在源文件中是唯一的。
第二, 源文件的全局变量不能被其他源文件所用,不能被其他的源文件所修改,保证变量的值是可靠的。
  D、文件作用域下声明的const的常量默认为static存储类型。
2、静态局部变量
定义:在局部变量前加上static关键字时,就定义了静态局部变量。
特点:
  A、该变量在全局数据区分配内存。
  B、初始化:如果不显式初始化,那么将被隐式初始化为0。
  C、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。

我的简单理解是这样的:
当static用来修饰局部变量时,它就改变了局部变量的存放位置,将其由原来的栈中存放改为全局静态储存区,但是没有改变变量的作用域,还是局限在局部的{}里。
当static用来修饰全局变量时,它就改变了全局变量的作用域,使其不能被别的程序extern,限制在了当前文件里,但是没有改变其存放位置,还是在全局静态储存区。
3、静态函数(注意与类的静态成员函数区别)
函数的定义和声明默认情况下在整个程序中是extern的,有时候可能需要使某个函数只在一个源文件中有效,不能被其他源文件所用,这时在函数前面加上static.
定义:在函数的返回类型前加上static关键字,函数即被定义成静态函数。
特点:
  A、静态函数只能在本源文件中使用(这是与普通函数区别)
  例(摘于C++程序设计教程---钱能主编P103):
        //file1.cpp
        void fn();
        void staticFn()
        void main()
        {
          fn();
          staticFn();
        }
        //file2.cpp
        #include<iostream.h>
        static void staticFn();
        void fn();
        void fn()
        {
          staticFn();
          cout << "this is fn() \n";
        }
        void staticFn()
        {
          cout << "this is staticFn() \n";
        }
连接时,将产生找不到函数staticFn()定义的错误。
作用:
第一, 它允许其他源文件建立并使用同名的函数,而不相互冲突
第二, 声明为静态的函数不能被其他源文件所调用,因为它的名字不能得到,
B、主意事项
  在文件作用域下声明的inline函数默认为static类型。

另其它::
C语言中提供了存储说明符auto,register,extern,static说明的四种存储类别。四存储类别说明符有两种存储期:自动存储期和静态存储期。其中auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块是被建立,它在该程序块活动时存在,退出该程序块时撤销。
关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量只能被定义该变量的函数所识别,但是不同于自动变量的是,static变量在其函数被调用退出后,仍保留其值。下次函数被调用时,可以访问最近一次被修改后的值。static变量的声明方法如下:
static int si = 1;
由于static的以上特性,可以实现一些特定的功能。下面说明常见的两种用途。
1. 统计函数被调用的次数
声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。这是统计函数被调用次数的最好的办法,因为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。测试代码如下:
/*-------------------------------------------------------------------
s_fun.c to count the number of a function's being called, use static var.
*/
#include <stdio.h>
int fun_1(int);
int main()
{
int i;
for (i = 1; i <= 5; i++)
fun_1(i);
return 0;
}
int fun_1(int x)
{
static count = 0;
count++;
printf("I have been called %d times.\n", count);

return 2*x;
}
输出结果为:
I have been called 1 times.
I have been called 2 times.
I have been called 3 times.
I have been called 4 times.
I have been called 5 times.
2. 减少局部数组建立和赋值的开销
变量的建立和赋值是需要一定的处理器开销的,特别是数组等含有较多元素的存储类型。在一些含有较多的变量并且被经常调用的函数中,可以将一些数组声明为static类型,以减少建立或者初始化这些变量的开销。示例代码如下:
/*--------------------------------------------------------------
array_1.c to test static array
*/
#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARRAY_SIZE 10000
#define CALL_TIMES 30000
int fun_1();
int fun_2();
int main()
{
int i;
char string2[10], *string3;
time_t t;
time(&t);
string3 = ctime(&t);
printf("time 1: %s", string3);

for (i = 1; i <= CALL_TIMES; i++)
{
fun_1();
}
time(&t);
string3 = ctime(&t);
printf("time 2: %s", string3);

for (i = 1; i <= CALL_TIMES; i++)
{
fun_2();
}
time(&t);
string3 = ctime(&t);
printf("time 3: %s", string3);

return 0;
}
int fun_1()
{
int a[ARRAY_SIZE], b[ARRAY_SIZE];
int i, t;

for ( i = 0; i < ARRAY_SIZE; i++)
{
a[i] = i;
b[i] = ARRAY_SIZE - i;
}

for ( i = 0; i < ARRAY_SIZE; i++)
{
t = a[i];
a[i] = b[i];
b[i] = t;
}

return 0;
}

int fun_2()
{
static int a[ARRAY_SIZE], b[ARRAY_SIZE];
int i, t;

for ( i = 0; i < ARRAY_SIZE; i++)
{
a[i] = i;
b[i] = ARRAY_SIZE - i;
}

for ( i = 0; i < ARRAY_SIZE; i++)
{
t = a[i];
a[i] = b[i];
b[i] = t;
}

return 0;
}

二、面象对象中的static关键字(主要指类中的static关键字)
1、静态数据成员
特点:
  A、内存分配:在程序的全局数据区分配。
  B、初始化和定义:
   a、静态数据成员定义时要分配空间,所以不能在类声明中定义。
   b、为了避免在多个使用该类的源文件中,对其重复定义,所在,不能在类的头文件中定义。
   c、静态数据成员因为程序一开始运行就必需存在,所以其初始化的最佳位置在类的内部实现。
  C、特点
   a、对相于 public,protected,private 关键字的影响它和普通数据成员一样,
   b、因为其空间在全局数据区分配,属于所有本类的对象共享,所以,它不属于特定的类对象,在没产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。

  D、访问形式
   a、 类对象名.静态数据成员名
   b、 类类型名:: 静态数据成员名
  E、静态数据成员,主要用在类的所有实例都拥有的属性上。比如,对于一个存款类,帐号相对   于每个实例都是不同的,但每个实例的利息是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局区的内存,所以节省存贮空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了,因为它们实际上是共用一个东西。
2、静态成员函数
特点:
  A、静态成员函数与类相联系,不与类的对象相联系。
  B、静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例。

作用:
  主要用于对静态数据成员的操作。
调用形式:
  A、类对象名.静态成员函数名()
  B、类类型名:: 静态成员函数名()

69,380

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧