精华内容
下载资源
问答
  • 静态变量的作用域是当前源文件,全局变量的作用域是整个可执行程序。 值得注意的是: 如果在头文件定义全局变量,在预编译期间#include的头文件会被拷贝进源文件中,编译器是不知道头文件的。 虽然全局变量是...

    全局变量和静态变量的存储方式是一样的,只是作用域不同。如果它们未初始化或初始化为0则会存储在BSS段,如果初始化为非0值则会存储在DATA段,见进程的地址空间分配一文。 静态变量的作用域是当前源文件,全局变量的作用域是整个可执行程序。 值得注意的是:

    • 如果在头文件定义全局变量,在预编译期间#include的头文件会被拷贝进源文件中,编译器是不知道头文件的。
    • 虽然全局变量是全局作用域,但需要extern关键字来声明以通过编译。因为C++是强类型语言,编译时需要根据变量声明做类型检查。

     

    原文链接:

    http://harttle.com/2015/09/30/cpp-static-and-global.html

    转载于:https://www.cnblogs.com/qingyuanjushi/p/5750648.html

    展开全文
  • 静态变量的作用域是当前源文件,全局变量的作用域是整个可执行程序。 值得注意的是:如果在头文件定义全局变量,在预编译期间#include的头文件会被拷贝进源文件中,编译器是不知道头文件的。虽然全局变量是全局作用...

    全局变量和静态变量的存储方式是一样的,只是作用域不同。如果它们未初始化或初始化为0则会存储在BSS段,如果初始化为非0值则会存储在DATA段,见进程的地址空间分配一文。静态变量的作用域是当前源文件,全局变量的作用域是整个可执行程序。 值得注意的是:

    • 如果在头文件定义全局变量,在预编译期间#include的头文件会被拷贝进源文件中,编译器是不知道头文件的。
    • 虽然全局变量是全局作用域,但需要extern关键字来声明以通过编译。因为C++是强类型语言,编译时需要根据变量声明做类型检查。

    全局变量的引用

    C++源文件中引用外部定义的全局变量和引用外部函数是一样的语法,通过extern来声明:

    // file: a.cpp
    #include<iostream>
    extern int a;
    int main() {
        std::cout<<b<<std::endl;
        return 0;
    }
    
    // file: b.cpp
    #include<iostream>
    int a = 2;
    

    然后分别编译这两个文件,链接生成a.out并执行它:

    $ g++ a.cpp b.cpp
    $ ./a.out
    b.cpp
    2
    

    extern只是在当前文件中声明有这样一个外部变量而已,并不指定它来自哪个外部文件。所以即使extern变量名错误当前源文件也能通过编译,但链接会出错。

    头文件中定义

    因为头文件可能会被多次引用,在预编译时被引用的头文件会被直接拷贝到源文件中再进行编译。一个常见的错误便是把变量定义放在头文件中,例如下面的变量int a

    // file: a.cpp
    #include <iostream>
    #include "b.h"
    int main() {
        std::cout<<a<<std::endl;
        return 0;
    }
    
    // file: b.cpp
    #include<iostream>
    #include"b.h"
    void f(){}
    
    // file: b.h
    int a = 2;
    

    头文件b.h中定义了int a,它被a.cppb.cpp同时引入。我们将a.cppb.cpp分别编译是没有问题的,然后链接时会抛出错误:

    duplicate symbol _a in:
        /tmp/ccqpfU5e.o
        /tmp/ccCRi9nO.o
    ld: 1 duplicate symbol for architecture x86_64
    collect2: error: ld returned 1 exit status
    

    两个.o文件中的_a名称发生了冗余,这是变量重定义错误。

    头文件中声明

    因为声明操作是幂等的,而多次定义会引发重定义错误。所以 头文件中不应包含任何形式的定义,只应该包含声明,正确的办法是变量定义总是在源文件中进行,而声明放在头文件中:

    #include <iostream>
    #include "b.h"
    int main() {
        std::cout<<a<<std::endl;
        return 0;
    }
    
    // file: b.cpp
    #include<iostream>
    #include"b.h"
    int a = 2;
    
    // file: b.h
    extern a;
    

    然后编译链接执行都会通过,输出2

    $ g++ a.cpp b.cpp
    $ ./a.out
    2
    

    编译器看到g++ a.cpp b.cpp时会自动去查找b.h并进行预编译操作,因此不需要显式指定b.h

    静态全局变量

    非静态全局变量是外部可链接的(external linkage),目标文件中会为它生产一个名称供链接器使用;而静态全局变量是内部可链接的(internal linkage),目标文件中没有为链接器提供名称。因此无法链接到其他文件中,因此静态变量的作用域在当前源文件(目标文件)。虽然静态和非静态全局变量可能存储在同一内存块,但它们的作用域是不同的。 来看例子:

    // file: a.cpp
    #include <iostream>
    extern int a;
    int main() {
        std::cout<<a<<std::endl;
        return 0;
    }
    
    // file: b.cpp
    static int a = 2;
    

    然后g++ a.cpp b.cpp时发生链接错:

    Undefined symbols for architecture x86_64:
      "_a", referenced from:
          _main in ccPLYjyx.o
    ld: symbol(s) not found for architecture x86_64
    collect2: error: ld returned 1 exit status
    

    链接时未找到名称_a,因此静态变量在编译得到的目标文件中没有为链接器提供名称。所以其他目标文件无法访问该变量,静态全局变量的作用域是当前源文件(或目标文件)。

    全局变量初始化

    全局变量比较特殊,初始化有两种方式:

    • 静态初始化(static initialization):对于定义时给出初始化参数的全局变量,其初始化在程序加载时完成。根据是否被初始化、是否被初始化为0会把它存储在BSS或者DATA段中,参见进程的地址空间分配
    • 动态初始化(dynamic initialization):定义变量时可以不给出初始化参数,而是在某个函数中进行全局变量初始化。

    对于静态初始化,看这个例子:

    class C{
    public:
        C(){ std::cout<<"init "; }
    };
    C c;
    int main() { std::cout<<"main"; return 0; }
    

    main()进入之前,程序加载时动态初始化,程序输出为一行init main

    关于全局变量的初始化顺序,同一源文件中的全局变量初始化顺序按照定义顺序,不同源文件(编译单元)的全局变量初始化顺序并未规定。因此软件设计时不要依赖于其他编译单元的静态变量,可以通过单例模式来避免这一点。


    原文地址https://harttle.land/2015/09/30/cpp-static-and-global.html

    展开全文
  • 变量的作用域

    2019-03-17 19:59:41
    被定义在所有函数以外变量,其作用域是整个PHP文件,但在用户自定义函数内部是不可用。如果希望在用户自定义函数内部使用全局变量,则要使用global关键字声明 静态变量 能够在函数调用结束后仍保留变量值,当...
    作用域 说明
    局部变量 在函数的内部定义的变量,其作用域是所在函数
    全局变量 被定义在所有函数以外的变量,其作用域是整个PHP文件,但在用户自定义函数内部是不可用的。如果希望在用户自定义函数内部使用全局变量,则要使用global关键字声明
    静态变量 能够在函数调用结束后仍保留变量值,当再次回到其作用域时,又可以继续使用原来的值。而一般变量在函数调用结束后,其存储的数据值将被清除,所占的内存空间被释放。使用静态变量时,先要用static来声明变量,把关键字static放在要定义的变量之前
    展开全文
  • 变量的作用域与生存期一、变量的作用域1.基本概念2.代码分析3.总结二、变量的生存期1.基本概念2.C语言的内存分布(1)基本概念(2)数据在内存中的分布3.总结 一、变量的作用域 1.基本概念 作用域的域英文翻译为...

    一、变量的作用域

    1.基本概念

    作用域的域英文翻译为scope,作用域即作用范围。作用域关键在于域,作用域影响的是访问权限,出了作用域就无权访问了。
    关于域:
    (1)有基于整体项目的域,可以做到整个项目的全局特性,我们称之为全局变量;
    (2)有基于文件的域,可以做到文件内全局特性,只能在文件内部访问,我们称之为静态全局变量;
    (3)有基于函数的域,在函数内部访问,我们称之为局部变量、静态局部变量以及函数形参;
    (4)有基于块的域,如if、while或者直接写{}包含的块域,在语句块内部访问,我们称之为局部变量或静态局部变量。

    注意
    其实全局变量也不是全域的,严谨的描述应该是全局变量的定义开始(包含作用域扩展定义)到其域结束。

    2.代码分析

    var_scope1.c

    int global1 = 111;         //全局变量
    static int global2 = 222;  //静态全局变量
    

    var_scope2.c

    #include <stdio.h>
    
    extern int global1;   //声明全局变量
    extern int global2;	  //声明静态全局变量
    
    void max(int *part1, int *part2)  //该函数形参可以跨函数访问,所以函数的形参(也是局部变量)的作用域是全域的。
    {
        static int temp;        //静态局部变量
        
        temp = *part1;
        *part1 = *part2;
        *part2 = temp;
    }
    
    int main() 
    {
        int part1 = 99;         //局部变量
        //part1 = part2;        //part2未定义
        static int part2 = 999;
        {
            int part3 = 100;
        }
        
        printf("global1 = %d\n", global1);
        //printf("global2 = %d\n", global2);  //global2未定义
        max(&part1, &part2);
        printf("part1 = %d, part2 = %d\n", part1, part2);//part1和part2的数值交换
        //printf("part3 = %d\n", part3);  //part3未定义
    	//printf("temp = %d\n", temp);    //temp未定义
    	
        return 0;
    }
    

    执行gcc var_scope1.c var_scope2.c -o var_scope
    运行var_scope得到运算结果。

    3.总结

    (1)全局变量在其他文件中使用,需在使用之前用external修饰声明全局变量;
    (2)static修饰全局变量,用于限定文件作用域;
    (3)auto只能修饰局部变量,一般省略不做修饰;
    (4)函数指针(即函数名)是全域的,但这个全域是相对的;
    (5)变量的作用域,影响的是编译期。

    二、变量的生存期

    1.基本概念

    生存期,关键在于生死期,和其定义的内存区域有关。
    • 定义变量(变量诞生)->申请内存
    • 释放内存(系统释放,手动释放)->变量死亡
    (1)全局变量、静态全局变量、静态局部变量存放在静态存储区(即全局区),其生存期从定义开始一直到程序运行结束;
    (2)局部变量、函数形参存放在栈区,生存期从定义开始一直到所在函数或语句块运行结束;
    (3)动态分配的变量存放在堆区,生存期从手动分配开始一直到手动释放结束。
    补充:
    • 递归的过程并没有代表函数的结束,进去函数后,分配一个栈帧空间。在该函数中递归时,又分配了一个栈帧空间,原先产生栈帧空间不会死亡,这样一直递归一直分配栈帧空间,所以递归的最后会耗尽程序的内存,导致程序崩溃。递归的过程可以很好体现变量的生存期过程,递归的使用会占用程序内存空间,所以要谨慎使用。
    test1.c

    #include <stdio.h>
    
    void func()
    {
        func();
    }
    
    int main() 
    {
        func();
    
        return 0;
    }
    

    运行结果:
    Segmentation fault (core dumped)
    • 关于死循环,可以理解为不断刷新内存空间,只会让程序卡主。
    test.2

    #include <stdio.h>
    #include <stdlib.h>
    
    void func()
    {
        int a = 1;
        int *b = (int *)malloc(sizeof(int));
        printf("%p\t%p\n", &a, &b);
        //free(b);   //堆内存不释放,死循环也是不断刷新内存空间
    }
    
    int main() 
    {
        while(1)
        {
            func();
        }
    
        return 0;
    }
    

    运行结果:

    2.C语言的内存分布

    (1)基本概念

    对于C语言程序而言,内存空间主要由四个部分组成,有代码段(.text)、全局段(分为DATA段(.data分为.rodata和.rwdata)和BSS段(.bss))、堆和栈。
    其中:
    • 全局段又称为静态存储段,有时候也称为静态存储区
    • 代码段、DATA段、BSS段是编译的时候由编译器分配
    • 堆是由程序员手动分配,栈是由系统自动分配。

    (2)数据在内存中的分布

    在这里插入图片描述
    在这里插入图片描述
    • 局部变量、函数形参、函数的返回值分为存放在栈中
    • 动态分配的变量都在堆中
    • 未初始化的全局变量、静态全局变量、全局变量都存放在静态存储区的BSS段
    • 初始化的的全局变量、静态全局变量、全局变量都存放在在静态存储区的DATA段
    • 字符串常量存放在在静态存储区的DATA段(.rodata)
    • 可执行程序(指令和常量)存放在代码区
    代码分析:

    int a = 0; //全局初始化区,a的值为0
    char *p1;  //全局未初始化区(初始化为NULL) 
    int main()   
    {   
         int b;                  //b分配在栈上,整型  
         char s[] = "abc";       //s分配在栈上,char *类型;"abc\0"分配在栈上,运行时赋值,函数结束销毁  
         char *p2;               //p2分配在栈上,未初始化   
         char *p3 = "123456";    //p3指向"123456"分配在字符串常量存储区的地址,编译时确定 
         static int c = 0;       //c在全局(静态)初始化区,可以多次跨函数调用而保持原值   
         p1 = (char *)malloc(10); //p1在全局未初始化区,指向分配得来得10字节的堆区地址   
         p2 = (char *)malloc(20); //p2指向分配得来得20字节的堆区地址  
         strcpy(p1, "123456");    //"123456"放在字符串常量存储区,编译器可能会将它与p3所指向的"123456"优化成一块 
         
         return 0; 
    }
    

    注意】现代编译器中关键字const修饰的全局变量、静态局部变量变量和静态全局变量就是存放在DATA段中的只读段,所以这些变量为只读属性,其值通过指针也不可改变。而const修饰的局部变量存放在栈中,可以通过指针改变其值。
    想进一步了解const修饰变量概念,点击下面链接:
    const定义常量和#define定义常量的区别

    3.总结

    (1)变量的生存期与变量所处内存区域有关,如存储在静态存储区的变量,生存期期就是从定义开始一直到程序结束;
    (2)变量的生存期,本质上就是从变量诞生(变量所处内存分配)到变量死亡(变量所处内存的释放)的整个过程;
    (3)变量的生存期,影响的是运行期;

    4.补充

    (1)光申请不释放->内存泄漏(生存期相关)
    (2)已释放再访问->非法访问(比如让关公再给你耍个大刀)
    (3)释放已经释放的空间(注意这是通过原有访问方式,其实还是第二个问题)->多重释放(比如我已经有一个房子,卖给了张三,我又把这个房子卖给李四,出错了,但是张三卖给李四不会出错)

    展开全文
  • 变量都有其自己的作用范围,超出了范围就不再有效。PHP中的变量有3种作用范围:局部变量,全局变量,和静态...全局变量的作用域是整个PHP文件。但是它的作用域达不到函数内部。如果想让一个在函数体内部的变量成为全...
  • C语言的变量的作用域和生存期

    万次阅读 多人点赞 2010-09-17 10:27:00
    extern变量的作用域是整个程序。 2.static(静态的) 在函数外部说明为static的变量的作用域为从定义点到该文件尾部;在函数内部说明为static的变量的作用域为从定义点到该局部程序块尾部。 3.auto(自动的
  • C语言中的变量作用域

    2010-10-13 17:47:00
    静态变量的作用范围要看静态变量的位置,如果在函数里,则作用范围 就是这个函数。 静态全局变量,只在本文件可以用,虽然整个程序包含多个文件,但静态全局变量只能用在定义它的那个文件里,却不能用在程序中的...
  • C语言变量作用域

    2020-07-30 19:21:16
    希望你每天醒来都阳光,不会因为别人几句话,几个表情和几个举止影响自己心情,好好生活,总会...静态全局变量,e变量只能在helloworld.c文件中调用,比如在该项目总新建一个test2.c文件,里面不能调用e变...
  • 全局变量,分配内存在静态存储区内存上面,其作用域是全局作用域,也就是整个程序生命周期内都可以使用,同时,有些程序并不是由一个源文件构成,可能有许多个源文件构成,全局变量只要在一个文件中定义,就...
  • 全局变量及其作用域-外部变量:extern

    千次阅读 2014-04-14 10:58:48
    作用域是从变量定义的位置开始,到整个源文件结束. 全局变量可以被作用域内的所有函数直接引用.如果在一个函数中改变了全局变量的值,那么后面的函数引用该变量时,得到的就是被改变后的值. 全局变量编译时,被分配在...
  • 作用域不同,全局变量的作用域是整个程序,静态遍地昂只在本源文件中有作用; 2.他们都保留在静态存储区; 全局变量作用于所有的源文件,其他不包含全局变量定义的源文件需要用extern关键字再次声明这个全局变量。而...
  • 0.1.1 变量的性质 在c中变量有三种性质: 1、存储期限:变量的存储...2、作用域:变量有块作用域也有文件作用域,结合序章第一张图可以明白块作用域是在某些程序块内起作用,文件作用域是整个c文件之内起作用。 3...
  • 全局变量的作用域是整个项目,它只需要在一个源文件中定义就可以作用于所有的源文件,其它不包括全局变量定义的文件需要用extern关键字再次声明这个全局变量。 全局变量、静态全局变量、静态局部变量都是在静态...
  • 全局变量和全局静态变量的区别

    千次阅读 2015-06-30 22:24:49
    1)全局变量是不显式用static修饰全局变量,全局变量默认是有外部链接性作用域是整个工程,在一个文件内定义全局变量,在另一个文件中,通过extern 全局变量名声明,就可以使用全局变量。 2)全局静态...
  • C 静态变量

    2014-10-10 23:46:48
    静态变量分为两种:全局静态变量和局部静态变量。全局静态变量是在函数之外定义的静态变量,局部静态变量是在某个函数(如...全局静态变量的作用域是从定义之处开始开始到结尾,全局静态变量对其他文件是不可见的(不
  • 动态变量与静态变量的区分就是定义该属性有无static修饰符。两者之间的主要区别, ①存储空间不同且生命期不同 动态变量:存储在动态数据区,跟随定义的函数出现/消失 静态变量:存储在静态数据区,在应用程序...
  • 1.两者作用域不同,全局变量的作用域是整个工程项目,静态全局变量作用域只在当前文件 2.全局变量在其他文件引用时,需使用extern声明 3.全局变量和静态全局变量都存储在静态存储区
  • 静态变量

    2010-11-18 20:06:00
    全局变量的作用域是整个源程序,当源程序有多个源文件组成时,全局变量在各个源程序文件都是有效的;而静态全局变量怎被限制了作用域,只在定义该变量的源文件内有用在同一程序的其他源文件不能使用! 还有静态全局...
  • <br />  全局变量在整个工程文件内都有效;静态全局变量只在定 义它的文件内有效;静态局部变量只在定义它...这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非
  • (1)下面拿静态全局变量和全局变量举...全局变量的作用域是整个源程序,当源程序有多个源文件组成时,全局变量在各个源程序文件都是有效的;而静态全局变量怎被限制了作用域,只在定义该变量的源文件内有用在同一程...
  • 由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。 static全局变量只初使化一次,防止在其他文件单元中被引用。 3、局部变量: 存储区栈区,离开...
  • 全局变量和静态变量的生命周期一样的,都要等到程序结束被释放 二者作用域不一样,静态变量取决于定义在哪里。全局变量(定义在函数外的变量),作用域整个文件,通过extern实现跨文件引用。 普通变量与全局变量...
  • Static变量的作用

    2016-07-31 21:47:41
    但是非静态全局变量的作用域是整个源程序,包括源程序中的各个单文件;而Static全局变量的作用域是单文件,源程序中的其他文件不能使用它,也就是作用域不同。 2. 局部变量和Static局部变量 一旦局部变量声明为...
  • 而按照作用域来,全局变量整个程序文件中有效,静态全局变量只在定义它的文件中有效,静态局部变量只在定义它函数内有效,程序分配一次内存,函数返回后任然有效,直到程序结束才销毁,局部变量
  • 全局变量与静态全局变量的区别

    千次阅读 2018-08-08 22:05:32
    一·全局变量作用域是整个工程,在一个文件内定义全局变量,在另一个文件中,通过extern 全局变量声明,就可以使用全局变量。   二·静态全局变量是显式用static修饰全局变量,作用域是声明此变量所在...
  • 关于静态变量

    2013-10-09 20:13:00
    静态局部变量的作用域是局部的,即存在于一个文件或者一个函数中,而静态全局变量则存在于整个函数中,即当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。。 静态局部变量和动态局部...
  • 静态局部变量:存放在静态区(全局区),程序开始到结束一直存在,作用范围在所声明定义的函数体内;...静态函数:静态函数限定了函数的作用域,用static修饰的函数只能在本源文件内使用,其它与普通函数并...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 434
精华内容 173
关键字:

静态变量的作用域是整个文件