选哲(小黑)'s profile俊杰的共享空间PhotosBlogLists Tools Help

Blog


    August 21

    static和extern

    借鉴篇

    一、c程序存储空间布局

    C程序一直由下列部分组成:

          1)正文段——CPU执行的机器指令部分;一个程序只有一个副本;只读,防止程序由于意外事故而修改自身指令;
          2)初始化数据段(数据段)——在程序中所有赋了初值的全局变量,存放在这里。
          3)非初始化数据段(bss段)——在程序中没有初始化的全局变量;内核将此段初始化为0。
          4)栈——增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回地址;环境信息)。
          5)堆——动态存储分。

    |-----------|
    |               |
    |-----------|
    |    栈        | 
    |-----------|
    |    |          |
    |   \|/        |
    |               |
    |               |
    |   /|\        |
    |    |          |
    |-----------|
    |    堆        |
    |-----------|
    | 未初始化  |
    |-----------|
    |   初始化   |
    |-----------|
    |  正文段    |
    |-----------|

    二、 面向过程程序设计中的static

    1. 全局静态变量

       在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。

       1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

       2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

       3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。


    看下面关于作用域的程序:
    //teststatic1.c
    void display();
    extern int n;
    int main()
    {
      n = 20;
      printf("%d\n",n);
      display();
      return 0;
    }
     
    //teststatic2.c 
    static int n;   //定义全局静态变量,自动初始化为0,仅在本文件中可见
    void display()
    {
      n++;
      printf("%d\n",n);
    }
     

    文件分别编译通过,但link的时候teststatic1.c中的变量n找不到定义,产生错误。
     
    定义全局静态变量的好处:

    <1>不会被其他文件所访问,修改

    <2>其他文件中可以使用相同名字的变量,不会发生冲突。

    2. 局部静态变量

      在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。

      1)内存中的位置:静态存储区

      2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

      3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

      注:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。

          当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。

    3. 静态函数

      在函数的返回类型前加上关键字static,函数就被定义成为静态函数。

      函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

      例如:
    //teststatic1.c
    void display();
    static void staticdis();
    int main()
    {
      display();
      staticdis();
      renturn 0;
    }
     
    //teststatic2.c
    void display()
    {
      staticdis();
      printf("display() has been called \n");
    }
     
    static void staticdis()
    {
      printf("staticDis() has been called\n");
    }
     
    文件分别编译通过,但是连接的时候找不到函数staticdis()的定义,产生错误。
     
    定义静态函数的好处:

    <1> 其他文件中可以定义相同名字的函数,不会发生冲突

    <2> 静态函数不能被其他文件所用。
     
    存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
     
    auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。

    关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。

    由于static变量的以上特性,可实现一些特定功能。

    1. 统计次数功能

    声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。这是统计函数被调用次数的最好的办法,因为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。代码如下:
     
    void count();
    int main()
    {
     int i;
     for (i = 1; i <= 3; i++)
      count();
      return 0;
    }
    void count()
    {
     static num = 0;
     num++;
     printf(" I have been called %d",num,"times\n");
    }

    输出结果为:
    I have been called 1 times.
    I have been called 2 times.
    I have been called 3 times.

    Comments (6)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Michael Fangwrote:
    VS 2005 Express于付费版本的区别

    在详细解读Express版与付费版本的差别之后,在此列出Express版的「十不一没有」,由前3个「不」即可发现Express版锁定在初学者及非商业用途。尽管如此,Visual Studio 2005 Express仍然是适合广大学生,软件开发爱好者,初学者的功能强大、易学易用的IDE.

    1.不能远程除错:限制本机开发与除错。

    2.不能远程访问数据库(Visual Web Developer 2005 Express版可以):主从架构的应用,限制只能存取本机数据库;Visual Web Developer 2005 Exress版是针对Web开发,内建的Web Development Server是开发与测试的网页服务器,也是只能存取本机的数据,不过部署到IIS以后,当然是可以远程访问数据库,否则就「Web」不起来了。

    3.数据库设计工具不能提供远程「数据连接」节点:存取数据库都限定本机,数据库的设计当然也限本机。

    4.不能支持Office开发:关于企业最常见的Office整合应用-汇出/汇入数据至Excel,再进一步制作成报表,Express版无法完成。

    5.不能远程部署:Standard以上版本开发的主从架构应用程序,提供ClickOnce机制,让使用者可以延用Windows Update的操作模式,由系统自动比对及下载更新程序,减少版本更新的困难度。Express版有劳手动部署。

    6.不能开发行动装置解决方案:无法开发PDA、智能型手机应用程序。

    7.不能整合SQL Server 2005:无法使用Express版撰写Stored Procedure(预存程序),也没有相对应的测试和版本控管功能。

    8.不支持64位编译:Visual Studio Team System才有的功能。

    9.不能协同开发:连远程除错与数据库联机都不行,当然不能协同开发。

    10.不能软件开发生命周期管理:需要此功能请购买Visual Studio 2005 Team System。

    11.没有Windows XP Style控件:没有可设定主题、颜色及渐层等外观的使用者控件(这只关乎系统的美丑,应该算是影响最小的)。

    还有更重要的限制-Express版关闭了加值接口(Add-In API),就是不能调用另外安装的第三方编写的API,这才是影响最大的关键。

    Sept. 14
    Michael Fangwrote:
    莫非这就是static变量的特点?
    Sept. 14
    Michael Fangwrote:
    突然发现count函数里num每次都被重新定义为0
    那3次的输出应该都是1啊
    Sept. 14
    SANDEE pengwrote:
    刚想表扬你知道更新了
    来这么个东西~
    Sept. 3
    Michael Fangwrote:
    静态变量和外部变量?
    Aug. 27
    yayawrote:
    这个.......迷茫~~`
    Aug. 21

    Trackbacks

    The trackback URL for this entry is:
    http://lujunjie820411xuanzhe.spaces.live.com/blog/cns!E818905AA4DD7CBA!207.trak
    Weblogs that reference this entry
    • None