c和c ++上下文中static,auto,global和local变量之间的区别

use*_*646 44 c c++ variables

我已经约了一些混乱static,auto,globallocal变量.

在某处我读到static变量只能在函数内访问,但在函数返回后它们仍然存在(保留在内存中).

但是,我也知道local变量也是一样的,那有什么区别呢?

Mik*_*our 88

这里有两个不同的概念:

  • 范围,确定可以访问名称的位置,以及
  • 存储持续时间,用于确定何时创建和销毁变量.

局部变量(迂腐地,具有块范围的变量)只能在声明它们的代码块中访问:

void f() {
    int i;
    i = 1; // OK: in scope
}
void g() {
    i = 2; // Error: not in scope
}
Run Code Online (Sandbox Code Playgroud)

全局变量(迂腐地,具有文件范围(在C中)或命名空间范围(在C++中)的变量)在声明之后的任何时候都可以访问:

int i;
void f() {
    i = 1; // OK: in scope
}
void g() {
    i = 2; // OK: still in scope
}
Run Code Online (Sandbox Code Playgroud)

(在C++中,情况更复杂,因为名称空间可以被关闭和重新打开,并且可以访问除当前作用域之外的作用域,名称也可以具有类作用域.但这非常偏离主题.)

自动变量(迂腐地,具有自动存储持续时间的变量)是局部变量,其寿命在执行离开其范围时结束,并在重新输入范围时重新创建.

for (int i = 0; i < 5; ++i) {
    int n = 0;
    printf("%d ", ++n);  // prints 1 1 1 1 1  - the previous value is lost
}
Run Code Online (Sandbox Code Playgroud)

静态变量(迂腐地,具有静态存储持续时间的变量)的生命周期一直持续到程序结束.如果它们是局部变量,那么当执行离开其范围时,它们的值仍然存在.

for (int i = 0; i < 5; ++i) {
    static int n = 0;
    printf("%d ", ++n);  // prints 1 2 3 4 5  - the value persists
}
Run Code Online (Sandbox Code Playgroud)

请注意,static除静态存储持续时间外,关键字具有各种含义.在全局变量或函数上,它为其提供内部链接,使其无法从其他翻译单元访问; 在C++类成员上,它意味着每个类有一个实例,而不是每个对象一个实例.此外,在C++中,auto关键字不再意味着自动存储持续时间; 它现在意味着自动类型,从变量的初始化器推导出来.

  • @ user1779646:"automatic"表示它们具有当前块的*存储持续时间*,并在离开块时被销毁."local"表示它们具有当前块的*scope*,并且无法从块外部访问.如果局部变量是"静态",则在离开块时不会被破坏; 它只是变得无法访问,直到重新进入块.请参阅我的答案中的`for`-loops示例,了解局部变量的自动和静态存储持续时间之间的差异. (17认同)
  • 回答,但我仍然无法得到自动变量和局部变量之间的差异,是不是它们都有运行功能的存储持续时间,请澄清. (2认同)
  • @MikeSeymour同意!从C++ 11开始它是"自动类型",而不是"自动存储"...... (2认同)

Fre*_*eak 12

首先,我说你应该google这个,因为它在很多地方都有详细定义.

本地
这些变量只存在于创建它们的特定函数中.它们不为其他功能和主程序所知.因此,它们通常使用堆栈来实现.一旦创建它们的函数完成,局部变量就不再存在.每次执行或调用函数时都会重新创建它们.

全局
这些变量可由包含该程序的任何函数访问(即已知).它们通过将内存位置与变量名称相关联来实现.如果调用该函数,则不会重新创建它们.

/* Demonstrating Global variables  */
    #include <stdio.h>
    int add_numbers( void );                /* ANSI function prototype */

    /* These are global variables and can be accessed by functions from this point on */
    int  value1, value2, value3;

    int add_numbers( void )
    {
        auto int result;
        result = value1 + value2 + value3;
        return result;
    }

    main()
    {
        auto int result;
        value1 = 10;
        value2 = 20;
        value3 = 30;        
        result = add_numbers();
        printf("The sum of %d + %d + %d is %d\n",
            value1, value2, value3, final_result);
    }


    Sample Program Output
    The sum of 10 + 20 + 30 is 60
Run Code Online (Sandbox Code Playgroud)

可以通过仔细放置声明来限制全局变量的范围.它们在声明中可见,直到当前源文件结束.

#include <stdio.h>
void no_access( void ); /* ANSI function prototype */
void all_access( void );

static int n2;      /* n2 is known from this point onwards */

void no_access( void )
{
    n1 = 10;        /* illegal, n1 not yet known */
    n2 = 5;         /* valid */
}

static int n1;      /* n1 is known from this point onwards */

void all_access( void )
{
    n1 = 10;        /* valid */
    n2 = 3;         /* valid */
}
Run Code Online (Sandbox Code Playgroud)

静态:
静态对象是一个从构造它到程序结束时持续存在的对象.因此,排除了堆栈和堆对象.但是全局对象,命名空间范围内的对象,在类/函数内声明为静态的对象以及在文件范围内声明的对象都包含在静态对象中.程序停止运行时会破坏静态对象.
我建议你看看这个教程列表

AUTO:
C,C++

(称为自动变量.)

默认情况下,在代码块中声明的所有变量都是自动的,但这可以使用auto关键字显式.[注1]未初始化的自动变量具有未定义的值,直到为其分配了其类型的有效值.[1]

使用存储类寄存器而不是auto是编译器将变量缓存在处理器寄存器中的提示.除了不允许在变量或其任何子组件上使用引用运算符(&)之外,编译器可以自由地忽略该提示.

在C++中,当执行到达声明位置时,将调用自动变量的构造函数.析构函数在到达给定程序块的末尾时被调用(程序块被大括号括起来).此功能通常用于管理资源分配和释放,例如打开然后自动关闭文件或释放内存.见WIKIPEDIA

  • 谷歌发现了大量不良信息和好消息.也许您可以从正确描述局部变量的源粘贴为*block*scope,而不是*function*scope; 并且全局变量也可以在函数之外以及在函数内部访问(当然,确保您在没有归属的情况下有权复制和粘贴). (8认同)
  • 你是如何在短短6分钟内输入这么多的! (4认同)
  • "你应该谷歌这个"(暗示:而不是看着Stackoverflow)开始变得既老又变成灰色区域.我想很多人都没有意识到SO*是谷歌搜索的结果. (2认同)

小智 6

区别在于静态变量是那些变量:它允许在函数的一次调用到另一次调用时保留值。但对于局部变量,作用域直到块/函数的生命周期为止。

例如:

#include <stdio.h>

void func() {
    static int x = 0; // x is initialized only once across three calls of func()
    printf("%d\n", x); // outputs the value of x
    x = x + 1;
}

int main(int argc, char * const argv[]) {
    func(); // prints 0
    func(); // prints 1
    func(); // prints 2
    return 0;
}
Run Code Online (Sandbox Code Playgroud)