天天看点

函数 - 关于变量(auto、static、register、extern、volatile、restrict)

1. 局部变量:

局部变量也叫自动变量, 它声明在函数开始, 生存于栈, 它的生命随着函数返回而结束.

#include <stdio.h>
             int                 main(         void                )
{
    auto          int                 i = 9; /* 声明局部变量的关键字是 auto; 因可以省略, 几乎没人使用 */                  
    printf("%d\n"               , i);  
    getchar();
             return                 0;
}
      

2. 全局变量:

全局变量声明在函数体外, 一般应在函数前; 每个函数都可以使用它, 不过全局变量应尽量少用.

#include <stdio.h>
             void                 add(         void                );
         void                 mul(         void                );
         int                 gi = 3; /* 全局变量 */             int                 main(         void                )
{    
    printf("%d\n"               , gi);  /* 3  */               
    add();
    printf("%d\n"               , gi);  /* 5  */               
    mul();
    printf("%d\n"               , gi);  /* 10 */               
      
    getchar();
             return                 0;
}
         void                 add(         void                ) {
    gi += 2;
}
         void                 mul(         void                ) {
    gi *= 2;
}
      

全局变量会被初始化为空, 而局部变量在没有赋值前是一个垃圾值:

#include <stdio.h>
             int                 gi; /* 全局变量 */             int                 main(         void                )
{
             int                 i; /* 句柄变量 */               
    
    printf("%d, %d\n"               , gi, i);
      
    getchar();
             return                 0;
}
      

当全局变量与局部变量重名时, 使用的是局部变量:

#include <stdio.h>
             int                 a = 111, b = 222;
         int                 main(         void                )
{
             int                 a = 123;
    printf("%d,%d\n"               , a, b); /* 123,222*/               
    getchar();    
             return                 0;
}
      

3. static 关键字:

用 static 关键字修饰的局部变量是静态局部变量;

静态局部变量存值如同全局变量, 区别在于它只属于拥有它的函数; 它也会被初始化为空.

#include <stdio.h>
             void                 fun1(         void                );
         void                 fun2(         void                );
         int                 main(         void                )
{    
             int                 i;
    
             for                 (i = 0; i < 10; i++) fun1();
    printf("---\n"               );
             for                 (i = 0; i < 10; i++) fun2();
    
    getchar();
             return                 0;
}
         void                 fun1(         void                ) {
             int                 n = 0;        /* 一般的局部变量 */               
    printf("%d\n"               , n++);
}
         void                 fun2(         void                ) {
             static              int                 n;     /* 静态局部变量; 会被初始化为空 */               
    printf("%d\n"               , n++);
}
      

用 static 关键字修饰的全局变量是静态全局变量; 静态全局变量只能用于定义它的单元.

//譬如在 File1.c 里面定义了:
             static              int                 num = 99;  /* 去掉前面的 static 其他单元才可以使用 */               
//在 File2.c 里使用:
               #include <stdio.h>
             extern              int                 num;
         int                 main(         void                )
{    
    printf("%d\n"               , num);
 
    getchar();
             return                 0;
}
      

用静态变量记录函数被调用的次数:

#include <stdio.h>
             int                 fun(         void                );
         int                 main(         void                )
{    
             int                 i;
             for                 (i = 0; i < 10; i++) {
        printf("函数被调用了 %2d 次;\n"               , fun());
    }     
    getchar();
             return                 0;
}
         int                 fun(         void                ) {
             static              int                 n;
             return                 ++n;
}
      

4. 寄存器变量(register):

书上说寄存器变量会尽量把变量放到寄存器(而不是栈或堆), 从而加快存取速度, 我试了一下, 效果一般般.

#include <stdio.h>
               #include <time.h>
               
#define TIME 1000000000
             int                 m, n = TIME; /* 全局变量 */             int                 main(         void                )
{   
    time_t start, stop;
             register              int                 a, b = TIME; /* 寄存器变量 */             int                 x, y = TIME;          /* 一般变量   */               
    
    time(&start);
             for                 (a = 0; a < b; a++);
    time(&stop);
    printf("寄存器变量用时: %d 秒\n"               , stop - start);
    time(&start);
             for                 (x = 0; x < y; x++);
    time(&stop);
    printf("一般变量用时: %d 秒\n"               , stop - start);
    time(&start);
             for                 (m = 0; m < n; m++);
    time(&stop);
    printf("全局变量用时: %d 秒\n"               , stop - start);
 
    getchar();
             return                 0;
}
      

4. extern 关键字:

使用外部全局变量应该用 extern 重新声明一下;

如果不使用 extern, 将是重新定义;

在链接阶段, 同一程序中不同单元的全局变量是共用的所以不能重新定义;

本例为了省事并没有涉及另一个文件, 只是把变量放在文件尾模拟了一下.

另外, extern 主要还是用于函数.

#include <stdio.h>
             extern              int                 g1;
         int                 main(         void                )
{    
             extern              int                 g2;
    printf("%d,%d\n"               , g1,g2);  
    getchar();
             return                 0;
}
         int                 g1 = 77;
         int                 g2 = 88;
      

5. volatile 关键字:

程序在使用变量时, 特别是连续多次使用变量时, 一般是载入寄存器, 直接从寄存器存取, 之后再还回内存;

但如果此变量在返回内存时, 假如内存中的值已经改变了(从外部修改了)怎么办?

为了避免这种情况的发生, 可以用 volatile 说明此变量, 以保证变量的每次使用都是直接从内存存取.

但这样肯定会影响效率, 幸好它并不常用.

另外: 如果 const volatile 同时使用, 这表示此变量只接受外部的修改.

#include <stdio.h>
             volatile              int                 num = 123;
         int                 main(         void                )
{    
    printf("%d\n"               , num);
    getchar();
             return                 0;
}
      

6. restrict 关键字:

restrict 有点和 volatile 相反; 不过 restrict 只是对指针.

好像 C++Builder 2009 并不支持它, 暂时无法测试.

继续阅读