Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > 转载:C/C++深层探索(八)
【标  题】:转载:C/C++深层探索(八)
【关键字】:C/C++
【来  源】:http://www.cublog.cn/u/6776/showart.php?id=125423

转载:C/C++深层探索(八)

Your Ad Here

静态内部变量

       上一篇文章,我们用static改变外部变量的链接性质,现在我们继续讨论static,不过,这一次它改变的是内部变量的存储性质(storage)。

       一般情况下,内部变量都被安排放在栈里面,函数被调用时才存在,函数结束时就消失。可是,有时我们可能想定义一种变量,编译器在数据段为它分配空间,从而它的生存期是整个程序的运行时间,但这些变量同时又是属于某个函数的内部变量,所以其他函数不能访问到它。很明显,这种变量既有外部变量的存储性质(放在数据段),又具有普通内部变量的可见范围(只能被自身所在的函数访问)。能做到吗?

       当然可以,只要使用static

       举个例子:

/*Example C code*/

#include<stdio.h>

int fun()

{

       static int a = 0;              //定义静态内部变量

       return (++a);

}

int main(void)

{

       printf(“a = %d\n”, fun());

       printf(“a = %d\n”, fun());

       return 0;

}

       编译、执行,先看看输出的结果:

$gcc test.c

$./a.out

a = 1

a = 2

$

       如果没有static关键字,那么两次输出的a显然应该相同,因为每一次进入函数,内部变量a就被初始化为“0,然后函数返回a的前缀自增值就结束了。现在有了static修饰,则内部变量a就不是放在栈而是数据段中,于是第二次调用函数fun时变量a的初值就是“1,因此这时函数的返回值就是“2

       也许有人会疑惑:第二次执行函数fun时,a不是应该再次被初始化为“0吗?

       实际上,静态内部变量a只会被初始化一次,看看汇编代码的片段:

$gcc –S test.c

$cat test.s

       .data

       .type       a.0, @object

       .size        a.0, 4

a.0:

       .long       0

      

       .text

.globl      fun

       .type       fun, @function

fun:

       pushl       %ebp

       movl       %esp, %ebp

       incl         a.0

       movl       a.0, %eax

       popl       %ebp

       ret

       ...

       注意一下会发现静态内部变量a在名字上被编译器作了一点“小动作”(各种编译器的具体做法不一定相同),成了“a.0,这是因为可能会在多个函数内部定义相同名称的静态内部变量,为了区分这些变量,编译器需要给与它们不同的名字。

       明显的,a.0被放在数据段,而且由于没有“.globl”语句,因此其他文件也看不见它,否则便可能会因为在不同的文件中定义了相同名称的变量而产生名字冲突。试想一下,有两个C文件:

1.c int f(){      static int a = 0;       }

2.c int g(){     static int a = 1;       }

       如果编译器把这两个变量a都改为“a.0,要是不把“.globl a.0去掉,则在链接的时候就会在全局空间出现两个“a.0而造成名字冲突。

       .long       0告诉编译器a.0的初始值是“0,这个值在编译的时候已经被存放在目标代码文件中,自然的,最后生成的可执行文件也存放了这么一个初始值,程序在加载到内存的时候,这个数据会被直接复制到内存。我们可以研究fun函数的代码,看看其中有没有类似下面的初始化语句:

movl       $0, a.0

       根本没有。

       进入fun函数,马上接着的就是inc(变量自增),事实表明,a.0在程序加载时已经完成了初始化。

       由于静态内部变量通过这种方式初始化(不仅静态内部变量,其实所有存放在.data段的数据比如外部变量都是这样初始化的),所以用来初始化静态内部变量的值必须是编译期便可求出的常数,像上面的“0

       譬如说,我们可以写:

       int f();

       void go(){      int a = f();      }

但不能写:

int f();

void go(){      static int a = f();     }

这是因为上面用来初始化静态内部变量的值不是常数而是一个函数的返回值,而函数的返回值不可能在编译时就算出来。

ID2 of Baidu:【上一篇】
转载:C/C++深层探索(七):【下一篇】
【相关文章】
  • 转载:C/C++深层探索(五)
  • 转载:C/C++深层探索(六)
  • 转载:C/C++深层探索(三)
  • 转载:C/C++深层探索(四)
  • C/C++没有数组
  • C/C++ 开发人员:充实您的 XML 工具箱
  • 转载:C/C++深层探索(一)
  • 转载:C/C++深层探索(二)
  • C/C++混合编译Makefile终于完全Debug了
  • C/C++ 笔试、面试题目大汇总
  • 【随机文章】
  • 关于在jbuilder中使用jndi配置datasource(tomcat4、jbuilder9-x)
  • 2D图像处理:斜切
  • 这个blog的确有问题
  • 微软发布WF教程及大量示例
  • 点阵图在矢量软件CD中的应用技巧(技巧篇)
  • CVS-Commands
  • 有的放矢!提前获得下载文件的详情
  • sqlserver数据库中统计email类型的sql语句
  • 一个在RCP中快速打开文件的小技巧
  • Debian下安装oracle 10g & 10gR2
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.