zoukankan      html  css  js  c++  java
  • 学点 C 语言(34): 函数 关于变量(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 并不支持它, 暂时无法测试.

  • 相关阅读:
    初学 Delphi 嵌入汇编[13] 地址参数用 [] 取值
    初学 Delphi 嵌入汇编[17] 逻辑运算
    初学 Delphi 嵌入汇编[11] 用汇编重写一个 Delphi 函数
    初学 Delphi 嵌入汇编[12] 在汇编代码中可以直接使用 Result
    初学 Delphi 嵌入汇编[19] Delphi 的无符号整数类型
    分享:tcpproxy实现
    Socket编程之简单介绍 蓝天下的雨 博客园
    分享:libuv 中文编程指南
    分享:《编程之美》求二叉树中节点的最大距离
    CentOS6.0下编译最新版本boost库
  • 原文地址:https://www.cnblogs.com/del/p/1347305.html
Copyright © 2011-2022 走看看