精华内容
下载资源
问答
  • 全局变量的作用

    千次阅读 2012-05-08 11:31:37
    一般全局变量的作用是增加函数间数据联系的渠道。因为全局变量在同一个文件中所有的函数都能访问,相当于各个函数间有了直接的传递通道。由于函数调用只能返回一个值,那么利用全局变量可以从函数中得到一个以上的...

    一般全局变量的作用是增加函数间数据联系的渠道。因为全局变量在同一个文件中所有的函数都能访问,相当于各个函数间有了直接的传递通道。由于函数调用只能返回一个值,那么利用全局变量可以从函数中得到一个以上的返回值.实例部分代码如下:

    #include<stdio.h>

    int hundreds=0;

    int tens=0;

    int units=0;


    void parsenum(int num)

    {

        hundreds=num/100;

        tens=num%100/10;

       units=num%10;

    }

    main()

    {

       ....

    parsenum(num);//调用函数函数后就可以得到全局变量的值

    printf(...);

    }


    展开全文
  • 局部变量和全局变量的作用

    千次阅读 2019-06-30 19:10:34
    局部变量:在函数内部定义的变量,只在函数内部起作用,函数执行结束,变量会自动删除 即在一个函数内部定义的变量,只在本函数范围内有效 ...由于同一文件中的所有函数都能引用全局变量的值 因...

    局部变量:在函数内部定义的变量,只在函数内部起作用,函数执行结束,变量会自动删除
    即在一个函数内部定义的变量,只在本函数范围内有效
    全局变量:“在函数外定义的变量”,即从定义变量的位置到本源文件结束都有效
    即可以被程序所有对象或者函数引用  
    当有外部变量时,main函数中的同名变量就是全局变量。如果没有外部变量,main函数里的变量依然是局部变量
    或者也可以直接在函数内部声明变量为全局变量

    目的:增加函数间数据联系的渠道。由于同一文件中的所有函数都能引用全局变量的值
    因此如果在一个函数中改变了全局变量的值,就能影响到其他函数中全局变量的值,相当于各个函数之间有直接的传递渠道

    a = 1
    print('out: ',id(a))查看变量的id
    def fun():
        global a
        a = 5
        print('in: ',id(a))
    fun()
    print(a)
    print(id(a))
    id是查看变量在内存中存放区域的编号
    

    在这里插入图片描述
    在这里插入图片描述
    此时函数内部定义的a是全局变量,所有的输出均为全局变量的信息
    在这里插入图片描述
    在这里插入图片描述
    此时函数外面的a是全局变量,所有的输出是全局变量的信息,局部变量只在函数内部起作用

    展开全文
  • 静态变量的作用域是当前源文件,全局变量的作用域是整个可执行程序。 值得注意的是:如果在头文件定义全局变量,在预编译期间#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

    展开全文
  • extern对于外部全局变量是有作用,但不能说对于局部变量有作用,而是对作用域(全局/局部)有作用; static既对于全局变量有作用,又对于局部变量有...所以只分析extern和static分别对全局变量的作用; 什么是源...

    extern对于外部全局变量是有作用,但不能说对于局部变量有作用,而是对作用域(全局/局部)有作用;

    static既对于全局变量有作用,又对于局部变量有作用;

    static对于局部变量的作用比较容易理解;

    extern只能去声明引用外部源文件的全局变量/函数,但是这个extern声明语句可以放在任意位置(全局/局部);

    所以只分析extern和static分别对全局变量的作用;

    什么是源文件(*.c/*.cpp),什么是头文件(*.h/*.hpp),两者不一样;

    (1)以下四种放在全局位置的包含变量的语句:

    extern int v;//声明去引用外部源文件的全局变量(可以写任意多次)

    int v;//定义本文件的变量(只能写一次)

    int v = 8;//定义本文件的变量(只能写一次)

    extern int v = 8;//声明去引用外部源文件的变量并且定义(如果外部源文件没有v的定义,那么编译无错,否则就是重定义);

    第四种语句就是鸡肋,所以有warning:

    (2)以下四种放在全局位置的包含函数的语句:

    extern int fun(int a);//声明去引用外部源文件的全局函数(可以写任意多次)

    int fun(int a);//声明去引用外部源文件或者声明本文件的函数(可以写任意多次)

    int fun(int a){........}//定义本文件的函数(只能写一次)

    extern int fun(int a){........}//鸡肋warning;

    (3)static对于全局变量的修饰

    静态全局变量,只能在本源文件内使用,不能在其他源文件中extern使用;

    解决重名问题,如果没有static修饰符,那么整个程序的所有源文件都不能使用相同名字的量;

    源文件.c.cpp不是头文件.h.hpp;

    #include "abc.h"只是简单的复制abc.h的内容到语句的位置而已,和直接把abc.h的内容写下来没有区别;

     

    (4)例子:

    源文件1:demo.cpp

    //demo.cpp
    #include <iostream>
    
    using namespace std;
    
    //stafun with the same name as the other src's static function, that's ok.
    int stafun(int a)
    {
    	cout << "main fun\n";
    }
    extern int extt;
    extern int extfun(int a);
    //extern int stat; //error
    //extern int stafun; //error
    
    int main()
    {
    	extt++;
    	extfun(6);
    
    	stafun(6);//call main fun
        return 0;
    }

    源文件2:d2.cpp

    //d2.cpp
    #include <iostream>
    
    using namespace std;
    int extt;
    int extfun(int a)
    {
    	cout << "extfun\n";
    	return a;
    }
    
    static int stat = 9;
    static int stafun(int a)
    {
    	cout << "stafun\n";
    	return a;
    }
    

    makefile:

    result : demo.cpp d2.cpp
    	 g++ -c demo.cpp
    	 g++ -c d2.cpp
    	 g++ -o res demo.o d2.o
    .PHONY : clean
    clean :
    	rm -f demo d2

    (5)多文件标准书写规范:

    为了减少代码的重复,具体就是extern引用其他源文件变量/类/函数的语句的重复,使用头文件;

    d2.h:(demo.cpp或其他任何想用d2内容的源文件在全局位置写#include "d2.h"就能减少代码量了)

    //d2.h
    extern int extt;
    extern int extfun(int a);

    对应的makefile修改为:

    result : demo.cpp d2.cpp d2.h
    	 g++ -c demo.cpp
    	 g++ -c d2.cpp
    	 g++ -o res demo.o d2.o
    .PHONY : clean
    clean :
    	rm -f demo d2

    (6)编译器对于头文件(.h/.hpp)和源文件(.c/.cpp)没有区分:

    头文件不是不能包含变量的定义,只是约定头文件这个带着.h.hpp的后缀的文件只写变量的声明;

    还约定#include只有头文件,不include源文件,防止多重定义的错误(链接时错误);

    (7)c++的class定义是用户自定义类型,不能用extern,static修饰类型的定义。

    (8)c++多个类文件也存在重定义的潜在问题;

    编写规范:(#progma once)(#ifndef SOME_CLASS #define SOME_CLASS <define class or whatever else> #endif)

    http://www.math.uaa.alaska.edu/~afkjm/csce211/handouts/SeparateCompilation.pdf

    C++ Separate Header and Implementation Files

    C++ classes (and often function prototypes) are normally split up into two files. The

    header file has the extension of .h and contains class definitions and functions. The

    implementation of the class goes into the .cpp file. By doing this, if your class

    implementation doesn’t change then it won’t need to be recompiled. Most IDE’s will do

    this for you – they will only recompile the classes that have changed. This is possible

    when they are split up this way, but it isn’t possible if everything is in one file (or if the

    implementation is all part of the header file).

    Simple example:

    File: Num.h

    class Num

    {

    private:

    int num;

    public:

    Num(int n);

    int getNum();

    };

    File: Num.cpp

    #include "Num.h"

    Num::Num() : num(0) { }

    Num::Num(int n): num(n) {}

    int Num::getNum()

    {

    return num;

    }

    File: main.cpp

    #include <iostream>

    #include "Num.h"

    using namespace std;

    int main()

    {

    Num n(35);

    cout << n.getNum() << endl;

    return 0;

    }

    To compile this from the command line we would use:

    g++ main.cpp Num.cpp

    Note the include statements; we must include the “Num.h” from anywhere we use it.

    Using #ifndef

    Sometimes we can end up including a header file multiple times. C++ doesn’t like this if

    it ends up redefining something again. In our previous example this didn’t happen

    because main.cpp and Num.cpp are compiled separately so the inclusion of Num.h causes

    no problem. But consider if we had another class in main that uses Num:

    File Foo.h (kept about as simple as possible, but not good practice to make Num public)

    #include "Num.h"

    class Foo

    {

    public:

    Num n;

    };

    We have no Foo.cpp since there is nothing to implement...

    Now in main:

    #include <iostream>

    #include "Num.h"

    #include "Foo.h"

    using namespace std;

    int main()

    {

    Num n(35);

    cout << n.getNum() << endl;

    Foo f;

    cout << f.n.getNum() << endl;

    return 0;

    }

    If we try to compile this we now get the error:

    In file included from Foo.h:1:0,

    from main.cpp:3:

    Num.h:1:7: error: redefinition of ‘class Num’

    In file included from main.cpp:2:0:

    Num.h:1:7: error: previous definition of ‘class Num’

    main.cpp: In function ‘int main()’:

    main.cpp:13:13: error: ‘class Foo’ has no member named ‘num’

    To fix this we can use #ifndef. This is called a

    directive

    as it is a message to the

    compiler, but not really a feature of the language. It tells the compiler to ignore what

    follows if it has already seen this stuff before. The format looks like this:

    #ifndef NUM_H

    #define NUM_H

    <define class or whatever else>

    #endif

    This says if “NUM_H” is not defined, then define it. So subsequent attempts to read this

    class result in skipping the definition since NUM_H is already defined. If we add this to

    our Num.h class then it will now compile and run.

    You can use any name but the recommendation is to use a name related to the class.

    The

    #pragma once

    directive

    The same functionality as #ifndef can be accomplished by adding #pragma once to the

    top of your file. This is the default used with Visual Studio.

    Separate Compilation

    With what we’ve done so far we split the header from the implementation. We’re actually

    still compiling both all the time though when we run the g++ command. To really get

    separate compilation we need to:

    1.

    Compile each .cpp file into an object file, which contains machine code for that

    file

    2.

    Link each object file into an executable

    To compile into an object file, you can use the command flag of –c:

    g++ -c main.cpp Num.cpp

    This produces a file main.o and Num.o. We can then link them. We can use g++ again

    to do this:

    g++ main.o Num.o

    We now have our familiar a.out program which we can run. An efficiency step is

    possible here because if Num never changes but main does change, then we can compile

    just main via:

    g++ -c main.cpp

    Then we can link them again but we didn’t have the overhead of compiling Num.cpp:

    g++ main.o Num.o

    With our little programs this saves virtually no time, but for really large programs this

    can be a significant savings in compile time. All of this stuff is done for you

    automatically by an IDE (which is one reason why they are great).

    The make utility

    It can also be a pain to compile lots of files when you have a big project. Once again, this

    functionality is provided for you as part of an IDE. But you have to do it yourself if you

    are compiling from the command line. Well, there is a solution in the

    make

    utility. If you

    run the command “make” then this program will look for a file named “Makefile” that

    contains information about program dependencies and what needs to be compiled.

    Here is an example for our particular setup:

    CFLAGS = -O

    CC = g++

    NumTest: main.o Num.o

    $(CC) $(CFLAGS) -o NumTest main.o Num.o

    main.o: main.cpp

    $(CC) $(CFLAGS) -c main.cpp

    Num.o: Num.cpp

    $(CC) $(CFLAGS) -c Num.cpp

    clean:

    rm -f core *.o

    This says that NumTest depends on main.o and Num.o and the second line says how to

    compile it. In turn, main.o is created by compiling main.cpp with the –c flag. We can

    compile by typing:

    make

    or

    make NumTest

    We can use the target of “clean” to delete object files and core dumps.

    Only files that have changed are recompiled. Here is a similar version using some more

    advanced features of Makefiles:

    CFLAGS = -O

    CC = g++

    SRC = main.cpp Num.cpp

    OBJ = $(SRC:.cpp = .o)

    NumTest: $(OBJ)

    $(CC) $(CFLAGS) -o NumTest $(OBJ)

    clean:

    rm -f core *.o

     

    展开全文
  • 具有文件作用域的变量称为全局变量,具有函数或者块作用域的变量称为局部变量 全部变量的初始值为0 当全局变量和局部变量名相同时,全局变量被屏蔽 为了访问局部变量,可以用域运算符“::”
  • 变量的作用变量的作用域是指变量的作用范围,即变量再程序中可以被访问的区域。 c语言中,每个变量都有一个有效的作用域。比如再函数内部定义的变量,不能再其他函数中引用 局部变量 指再函数体定义的变量和函数...
  • 全局变量:定义在.py模块内部,作用在整个.py模块。生命周期:从变量被创造开始到.py模块结束死亡。 下面用案例具体来说明它的作用域: (1): def Demo1(): num = 1 print(num) Demo1() print(num) ...
  • 本文主要介绍C++中的局部变量、全局变量、以及动态内存管理的变量。本文不涉及静态变量static,所以描述的观点不包括static变量。...这部分变量存储在 全局/静态存储区,这部分变量的作用域是从...
  • 1.c++中static int a,其中a的作用域是local的,即当前文档。 2.c++中const int a=10;其中a的作用域是local的,即当前文档,extern const int a=10,的作用域是全局的。
  • 全局变量的作用范围和顺序

    千次阅读 2017-08-04 10:44:21
    全局变量 Ⅰ.作用范围:所有区间 Ⅱ.执行顺序:由上到下,而不是同时指向所有区间 eg: public class test3{ public static void main(String[] args){ int a=1; while(a>=1&&a System.out.println(a); //测试 ...
  • 1.之前我理解类是为了节省时间演化来,因此里面静态属性应该和模块中的全局变量作用范围类似,那类中静态属性应该在整个类中都能访问。但实际为代码段所示。 2. ``` 2.1 全局变量能被内部定义函数所...
  • <!DOCTYPE html> <title>Webville Tunes var avatar = "genertic"; var skill = 1.0; var pointsPerLevel = 1000; var userPoints = 2008;...在函数外全局变量,在函数内是局部变量
  • 与static变量相比,全局变量的优势就是初始化的时刻更确定。googletest使用全局变量来注册每个test case。这样做的好处还有就是对框架的侵入最少,其他的方案或者是显式的注册,或者是通过Include的方式,这些都不如...
  • // 方法1 static int n; // 方法二 namespace { int n; }
  • 全局变量的作用域是整个程序,局部变量的作用域是定义变量的函数内部,离开函数局部变量失效。 2.一个局部函数不能使用另一个局部函数中定义的变量。 http://c.biancheng.net/cpp/html/62.html ...
  • 1调用函数时,Python 会优先在局部作用域内寻找变量,找不到再去外层的全局变量寻找,如果都找不到则报NameError错误 # 这里 rule 在函数外是全局变量 rule = '965 工作制' def busy_company(): # 这里 ...
  • 变量起作用的范围称为变量的作用域,不同的作用域内同名变量之间互不影响。变量分为:全局变量、局部变量。 全局变量: 在函数和类定义之外声明的变量,作用域为定义的模块,从定义位置开始直到模块结束。 全局...
  • 变量定义以后,是有一定的使用范围,称之为变量的作用域。比如Java中,变量的使用范围是变量声明时所在的{}范围,而python的作用域对应的为同一个缩进。按着变量的使用范围给变量划分成如下两种: 1.全局变量:...
  • Java静态全局变量与全局变量的区别

    千次阅读 2019-01-16 09:58:55
    Static全局变量与普通的...这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个原文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量...
  • 这两者的区别:非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序...
  • 全局变量 作用域:允许在定义区域使用,但理论上无法...实现全局变量和局部变量互访方法 使用$GLOBALS[‘键名’],通过访问数组方式。 通过方法传递参数。(推荐) 使用global 关键字定义变量。 ...
  • 全局变量和静态全局变量

    千次阅读 2019-04-15 00:01:34
    这两者在存储方式上并无不同,区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的...
  • 1、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?...这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件
  • 1.两者作用域不同,全局变量的作用域是整个工程项目,静态全局变量作用域只在当前文件 2.全局变量在其他文件引用时,需使用extern声明 3.全局变量和静态全局变量都存储在静态存储区
  • 全局变量作用

    千次阅读 2018-10-11 15:58:07
    未经过var定义全局变量的隐患 var 定义的全局变量和未经过 var 定义的全局变量之间存在些差异,就是通过 delete 操作符让变量未定义的能力。 通过 var 创建的全局变量(任何函数之外创建的)是不能被删除的。 无 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,798
精华内容 12,319
关键字:

全局变量的作用