zoukankan      html  css  js  c++  java
  • c++各类变量汇总

    一、局部变量和全局变量:

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

    1. #include <stdio.h>  
    2.   
    3. int main(void)  
    4. {  
    5.     auto int i = 9; <span style="white-space:pre">  </span>//声明局部变量的关键字是 auto; 因可以省略,所以几乎没人使用  
    6.   
    7.     printf("%d ", i);    
    8.     getchar();  
    9.     return 0;  
    10. }  
    #include <stdio.h>
    
    int main(void)
    {
        auto int i = 9; 	//声明局部变量的关键字是 auto; 因可以省略,所以几乎没人使用
    
        printf("%d
    ", i);  
        getchar();
        return 0;
    }
    
    1.   
    
    

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

    1. #include <stdio.h>  
    2.   
    3. void add(void);  
    4. void mul(void);  
    5.   
    6. int gi = 3; <span style="white-space:pre">      </span>//全局变量(声明在函数外)  
    7.   
    8. int main(void)  
    9. {      
    10.     printf("%d ", gi); //输出的是 3  
    11.   
    12.     add();  
    13.     printf("%d ", gi); //输出的是 5  
    14.   
    15.     mul();  
    16.     printf("%d ", gi); //输出的是 10  
    17.         
    18.     getchar();  
    19.     return 0;  
    20. }  
    21.   
    22. void add(void) {  
    23.     gi += 2;  
    24. }  
    25.   
    26. void mul(void) {  
    27.     gi *= 2;  
    28. }  
    #include <stdio.h>
    
    void add(void);
    void mul(void);
    
    int gi = 3; 		//全局变量(声明在函数外)
    
    int main(void)
    {    
        printf("%d
    ", gi); //输出的是 3
    
        add();
        printf("%d
    ", gi); //输出的是 5
    
        mul();
        printf("%d
    ", gi); //输出的是 10
          
        getchar();
        return 0;
    }
    
    void add(void) {
        gi += 2;
    }
    
    void mul(void) {
        gi *= 2;
    }

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

    1. #include <stdio.h>  
    2.   
    3. int gi;<span style="white-space:pre">           </span>//全局变量  
    4.   
    5. int main(void)  
    6. {  
    7.     int i;<span style="white-space:pre">        </span>//局部变量  
    8.       
    9.     printf("%d, %d ", gi, i);  
    10.         
    11.     getchar();  
    12.     return 0;  
    13. }  
    #include <stdio.h>
    
    int gi;			//全局变量
    
    int main(void)
    {
        int i;		//局部变量
        
        printf("%d, %d
    ", gi, i);
          
        getchar();
        return 0;
    }

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

    1. #include <stdio.h>  
    2.   
    3. int a = 111, b = 222;  
    4.   
    5. int main(void)  
    6. {  
    7.     int a = 123;  
    8.     printf("%d,%d ", a, b);<span style="white-space:pre">  </span>//输出的是 123,222  
    9.   
    10.     getchar();      
    11.     return 0;  
    12. }  
    #include <stdio.h>
    
    int a = 111, b = 222;
    
    int main(void)
    {
        int a = 123;
        printf("%d,%d
    ", a, b);	//输出的是 123,222
    
        getchar();    
        return 0;
    }


    二、对象的生存周期(lifetime)

    (1)静态生存周期(即全局变量的生存周期)

    具有静态生存周期的所有对象,都是在程序开始执行之前就被事先创建和初始化。它们的寿命覆盖整个程序的执行过程。如在函数内定义了一个static变量,那第一次调用该函数后,该变量的值将会被保留,当第二次被调用时,该变量的值还是第一次调用结束时的值。

    (2)自动生存周期(即局部变量的生存周期)

    自动生存周期的对象的寿命由“对象定义所处在的大括号{}”决定。每次程序执行流进入一个语句块,此语句块自动生存周期的对象就会被创建一个新实例,同时被初始化。

    三、标识符的链接(linkage)

    (1)外部链接

    表示在整个程序中(多个程序文件)是相同的函数或对象。常见的有,在函数体外声明的extern变量。

    (2)内部链接

    表示只在当前程序文件中是相同的函数或对象。其它程序文件不能对其进行访问。常见的有,在函数体外声明的static变量。

    (3)无链接

    一般声明在函数内部的auto、register变量、还有函数的参数,都是无链接。它的作用域是函数内部。

    四、存储类型修饰符总结:

    存储类型修饰符可以修改标识符的链接和对应对象的生存周期;标识符有链接,而非生命周期;对象有生存周期,而非链接;函数标识符只可用static、extern修饰,函数参数只可用register修饰。

    (1)auto(对应自动生存周期)

    auto修饰符只能用在函数内的对象声明中,即仅在语句块内使用。

    声明中有auto修饰符的对象具有自动生存周期。

    它们仅存在于被定义的当前执行代码块中,即局部变量在进入模块时生成,在退出模块时消亡。

    定义局部变量的最常见的代码块是函数。 语言中包括了关键字auto,它可用于定义局部变量。但自从所有的非全局变量的缺省值假定为auto以来,auto就几乎很少使用了。

    (2)static(对应静态生存周期)

    如果是定义在函数外,那么该对象具有内部链接,其它程序文件不能对其访问。如果是定义在函数内,那么该对象具有无链接,函数外不能对其访问。

    (注意:static变量初始化时,只能用常量)

    用 static 关键字修饰的局部变量称为静态局部变量。

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

    1. #include <stdio.h>  
    2.   
    3. void fun1(void);  
    4. void fun2(void);  
    5.   
    6. int main(void)  
    7. {      
    8.     int i;  
    9.       
    10.     for (i = 0; i < 10; i++) fun1();  
    11.     printf("--- ");  
    12.     for (i = 0; i < 10; i++) fun2();  
    13.       
    14.     getchar();  
    15.     return 0;  
    16. }  
    17.   
    18. void fun1(void) {  
    19.     int n = 0;<span style="white-space:pre">            </span>//一般的局部变量  
    20.     printf("%d ", n++);  
    21. }  
    22.   
    23. void fun2(void) {  
    24.     static int n;<span style="white-space:pre">     </span>//静态局部变量,会被初始化为空  
    25.     printf("%d ", n++);  
    26. }  
    #include <stdio.h>
    
    void fun1(void);
    void fun2(void);
    
    int main(void)
    {    
        int i;
        
        for (i = 0; i < 10; i++) fun1();
        printf("---
    ");
        for (i = 0; i < 10; i++) fun2();
        
        getchar();
        return 0;
    }
    
    void fun1(void) {
        int n = 0;			//一般的局部变量
        printf("%d
    ", n++);
    }
    
    void fun2(void) {
        static int n;		//静态局部变量,会被初始化为空
        printf("%d
    ", n++);
    }

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

    1. //譬如在 File1.c 里面定义了:  
    2. static int num = 99;  /* 去掉前面的 static 其他单元才可以使用 */  
    3.   
    4. //在 File2.c 里使用:  
    5. #include <stdio.h>  
    6.   
    7. extern int num;  
    8.   
    9. int main(void)  
    10. {      
    11.     printf("%d ", num);  
    12.    
    13.     getchar();  
    14.     return 0;  
    15. }  
    //譬如在 File1.c 里面定义了:
    static int num = 99;  /* 去掉前面的 static 其他单元才可以使用 */
    
    //在 File2.c 里使用:
    #include <stdio.h>
    
    extern int num;
    
    int main(void)
    {    
        printf("%d
    ", num);
     
        getchar();
        return 0;
    }
    



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

    1. #include <stdio.h>  
    2.   
    3. int fun(void);  
    4.   
    5. int main(void)  
    6. {      
    7.     int i;  
    8.     for (i = 0; i < 10; i++) {  
    9.         printf("函数被调用了 %2d 次; ", fun());  
    10.     }       
    11.     getchar();  
    12.     return 0;  
    13. }  
    14.   
    15. int fun(void) {  
    16.     static int n;  
    17.     return ++n;  
    18. }  
    #include <stdio.h>
    
    int fun(void);
    
    int main(void)
    {    
        int i;
        for (i = 0; i < 10; i++) {
            printf("函数被调用了 %2d 次;
    ", fun());
        }     
        getchar();
        return 0;
    }
    
    int fun(void) {
        static int n;
        return ++n;
    }
    

    (3)const

    (4)extern(对应静态生存周期)

    extern 意为“外来的”。它的作用在于告诉编译器:这个变量或者函数的定义在别的地方,当遇到此变量或函数时应到其他模块中寻找其定义。

    (PS:这个变量,它可能不存在于当前的文件中,但它肯定要存在于工程中的某一个源文件中或者一个Dll的输出中。)

    1. #include <stdio.h>  
    2.   
    3. extern int g1;  
    4.   
    5. int main(void)  
    6. {      
    7.     extern int g2;<span style="white-space:pre">    </span>//告诉编译器g2定义在其他地方  
    8.   
    9.     printf("%d,%d ", g1,g2);    
    10.     getchar();  
    11.     return 0;  
    12. }  
    13.   
    14. int g1 = 77;  
    15. int g2 = 88;  
    #include <stdio.h>
    
    extern int g1;
    
    int main(void)
    {    
        extern int g2;	//告诉编译器g2定义在其他地方
    
        printf("%d,%d
    ", g1,g2);  
        getchar();
        return 0;
    }
    
    int g1 = 77;
    int g2 = 88;
    

    使用extern时,注意不能重复定义,否则编译报错,如:

    程序文件一:

    1. extern int a = 10; <span style="white-space:pre">   </span>//编译警告,extern的变量最好不要初始化   
    extern int a = 10; 	//编译警告,extern的变量最好不要初始化 

    程序文件二:

    1. extern int a = 20; <span style="white-space:pre">   </span>//重复定义,应改为extern int a;   
    extern int a = 20; 	//重复定义,应改为extern int a; 

    (一般最好这样,如果需要初始化,可把extern修饰符去掉(但也不要重复定义),另外如果其它程序文件也需要用到该变量,可用extern来声明该变量。这样会比较清晰。)

    另外,extern也可用来进行链接指定。

    (5)volatile

    (6)register(即寄存器变量,对应自动生存周期)

    当声明对象有自动生存周期时,可以使用register修饰符。因此,register也只能用在函数内的声明中。

    register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中(而不是栈或堆),以加快其存储速度。然而,编译器不见得会这么做,因此效果一般般。了解一下就行,不建议使用。

    1. #include <stdio.h>  
    2. #include <time.h>  
    3.   
    4. #define TIME 1000000000  
    5.   
    6. int m, n = TIME;<span style="white-space:pre">      </span>//全局变量  
    7.   
    8. int main(void)  
    9. {     
    10.     time_t start, stop;  
    11.   
    12.     register int a, b = TIME;<span style="white-space:pre"> </span>//寄存器变量  
    13.     int x, y = TIME;<span style="white-space:pre">      </span>//一般变量  
    14.       
    15.     time(&start);  
    16.     for (a = 0; a < b; a++);  
    17.     time(&stop);  
    18.     printf("寄存器变量用时: %d 秒 ", stop - start);  
    19.   
    20.     time(&start);  
    21.     for (x = 0; x < y; x++);  
    22.     time(&stop);  
    23.     printf("一般变量用时: %d 秒 ", stop - start);  
    24.   
    25.     time(&start);  
    26.     for (m = 0; m < n; m++);  
    27.     time(&stop);  
    28.     printf("全局变量用时: %d 秒 ", stop - start);  
    29.    
    30.     getchar();  
    31.     return 0;  
    32. }  
    #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 秒
    ", stop - start);
    
        time(&start);
        for (x = 0; x < y; x++);
        time(&stop);
        printf("一般变量用时: %d 秒
    ", stop - start);
    
        time(&start);
        for (m = 0; m < n; m++);
        time(&stop);
        printf("全局变量用时: %d 秒
    ", stop - start);
     
        getchar();
        return 0;
    }

    使用register修饰符有几点限制:

     

      首先,register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。

     

      其次,因为register变量有可能被存放到寄存器中而不是内存中,所以不能用“&”来获取register变量的地址。

     

      总的来说,由于寄存器的数量有限,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。

     

      在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。

     

      早期的C编译程序不会把变量保存在寄存器中,除非你命令它这样做,这时register修饰符是C语言的一种很有价值的补充。然而,随着编译程序设计技术的进步,在决定那些变量应该被存到寄存器中时,现在的C编译环境能比程序员做出更好的决定。实际上,许多编译程序都会忽略register修饰符,因为尽管它完全合法,但它仅仅是暗示而不是命令。

    (7)缺省修饰符

    函数内,与auto相同,函数外,与extern相同。



    五、概括性例子:

    1. int func1(void); <span style="white-space:pre"> </span>//func1具有外部链接  
    2. int a = 10; <span style="white-space:pre">      </span>//a具有外部链接,静态生存周期      
    3. extern int b = 1; <span style="white-space:pre">    </span>//b具有外部链接,静态生存周期。但编译会有警告extern变量不应初始化,同时也要注意是否会重复定义  
    4. static int c; <span style="white-space:pre">        </span>//c具有内部链接,静态生存周期  
    5. static int e; <span style="white-space:pre">        </span>//e具有内部链接,静态生存周期  
    6. static void func2(int d)  
    7. {  
    8. <span style="white-space:pre">  </span>//func2具有内部链接;参数d具有无链接,自动生存周期  
    9. <span style="white-space:pre">  </span>extern int a; <span style="white-space:pre"> </span>//a与上面的a一样(同一变量),具有外部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明  
    10. <span style="white-space:pre">  </span>int b = 2; <span style="white-space:pre">    </span>//b具有无链接,自动生存同期。并且将上面声明的b隐藏起来  
    11. <span style="white-space:pre">  </span>extern int c; <span style="white-space:pre"> </span>//c与上面的c一样,维持内部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明  
    12. <span style="white-space:pre">  </span>//如果去掉了extern修饰符,就跟b类似了,无链接,自动生存周期,把上面声明的c隐藏起来  
    13. <span style="white-space:pre">  </span>static int e; <span style="white-space:pre"> </span>//e具有无链接,静态生存周期。并且将上面声明的e隐藏起来;初始化值为0  
    14. <span style="white-space:pre">  </span>static int f; <span style="white-space:pre"> </span>//f具有无链接,静态生存周期  
    15. }    
    int func1(void); 	//func1具有外部链接
    int a = 10; 		//a具有外部链接,静态生存周期    
    extern int b = 1; 	//b具有外部链接,静态生存周期。但编译会有警告extern变量不应初始化,同时也要注意是否会重复定义
    static int c; 		//c具有内部链接,静态生存周期
    static int e; 		//e具有内部链接,静态生存周期
    static void func2(int d)
    {
    	//func2具有内部链接;参数d具有无链接,自动生存周期
    	extern int a; 	//a与上面的a一样(同一变量),具有外部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明
    	int b = 2; 	//b具有无链接,自动生存同期。并且将上面声明的b隐藏起来
    	extern int c; 	//c与上面的c一样,维持内部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明
    	//如果去掉了extern修饰符,就跟b类似了,无链接,自动生存周期,把上面声明的c隐藏起来
    	static int e; 	//e具有无链接,静态生存周期。并且将上面声明的e隐藏起来;初始化值为0
    	static int f; 	//f具有无链接,静态生存周期
    }  

    相关链接参考:

    http://developer.51cto.com/art/201105/261465.htm

    http://apps.hi.baidu.com/share/detail/30353645

    http://www.cnblogs.com/del/archive/2008/12/04/1347305.html

  • 相关阅读:
    Oracle- 表的自增长创建
    C#- 写Windows服务
    基于redis分布式缓存实现(新浪微博案例)
    分布式集群系统下的高可用session解决方案
    Hibernate 缓存介绍
    MongoDB 安装(Window/Linux)
    MongoDB 优点
    MongoDB 介绍
    浅析数据一致性
    mysql常用函数汇总
  • 原文地址:https://www.cnblogs.com/fengting/p/5749684.html
Copyright © 2011-2022 走看看