C/C++ 中堆和栈及静态数据区详解

2020-01-06 17:17:33王振洲
 

   add()函数被调用了100次,num的值从1一直变到100,这样就可以求出它们的和了。如果写成int num=0;那就是求1+1+……+1这100个1的值了。

   实际上类似的这类问题我们可以通过递归函数来解决,什么是递归,我们下一节介绍。

      3.外部存储类型

  外部存储类型声明了程序将要用到的、但尚未定义的外部变量。通常,外部存储类型都是用于声明在另一个转换单元中定义的变量。下面举一个例子,这个例子包括两个文件。


     /*1.C*/
    void a();

    main()
    {
     extern int num;
     a();
     printf("%dn",num);
    }

    /*2.C*/
    int num;

    void a()
    {
     num=5;
    }

  这两个程序是分别编译的,然后连接成一个执行文件。具体如何操作,可以查看一些手册,这儿我简单说了一下。把上面两个文件都编译好后,再制作一个.prj文件,里面的内容是:

  1.c
  2.c

  只有这两行,这可在编辑状态下写成,存盘,取名为1.prj。

  然后选择project选项,选择project name,填入1.prj文件名,按F9后,即可生成1.exe文件。  

  main()函数中变量num是在另一个文件中定义的。因此,当编译器编译1.c时,无法确定该变量的地址。这时,外部存储类型声明告诉编译器,把所有对 num的引用当作暂且无法确定的引用,等到所有便宜好的目标代码连接成一个可执行程序模块时,再来处理对变量num的引用。  

  外部变量的声明既可以在引用它的函数的内部,也可以在外部。如果变量声明在函数外部,那么同一转换单元内的所有函数都可以使用这个外部变量。反之,如果在函数内部,那么只有这一个函数可以使用该变量。

  前面说了文件作用域的问题,如果在声明全局变量时,加上static修饰符,那么该变量只在当前文件内可见,而extern又可以引用其它文件里的变量。 所以在一个大型程序中,每个程序员只是完成其中的一小块,为了让自己的变量不让其他程序员使用,保持一定的独立性,经常在全局变量前加static。我们可以这样来说明一下:

  还是上面的两个文件,现在再增加一个文件3.c,内容为:


 static int num;

 void a()
 {
  num=6;
 }
 

   把1.prj文件后面加上3.c 这样,我们生成的1.exe文件,执行时输出是5,而不是6。因为3.c文件的num变量增加了文件作用域,在其他文件中是无法使用它的。

  4.寄存器存储类型

  被声明为寄存器存储类型的变量,除了程序无法得到其地址外,其余都和自动变量一样。至于什么是变量地址,以后说指针时会详细介绍。