web-dev-qa-db-ja.com

cおよびc ++のコンテキストにおける静的変数、自動変数、グローバル変数、ローカル変数の違い

staticautoglobal、およびlocal変数について少し混乱しています。

どこかでstatic変数は関数内でしかアクセスできないが、関数が戻った後もまだ存在している(メモリに残っている)と読みました。

しかし、local変数も同じことを知っているので、違いは何ですか?

44
user1779646

ここには2つの異なる概念があります。

  • scope。名前にアクセスできる場所を決定します。
  • ストレージ期間。変数が作成および破棄されるタイミングを決定します。

ローカル変数(特に、ブロックスコープの変数)は、それらが宣言されているコードブロック内でのみアクセス可能です。

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

グローバル変数(詳しくは、ファイルスコープ(Cで)または名前空間スコープ(C++で)の変数)は、宣言後の任意の時点でアクセス可能です:

int i;
void f() {
    i = 1; // OK: in scope
}
void g() {
    i = 2; // OK: still in scope
}

(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
}

静的変数(詳しくは、静的ストレージ期間の変数)の有効期間は、プログラムの終了まで続きます。ローカル変数の場合、実行がスコープを離れても値は保持されます。

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

staticキーワードには、静的な保存期間以外にもさまざまな意味があることに注意してください。グローバル変数または関数では、内部リンケージを指定するため、他の翻訳単位からはアクセスできません。 C++クラスメンバでは、オブジェクトごとに1つではなく、クラスごとに1つのインスタンスがあることを意味します。また、C++では、autoキーワードは自動ストレージ期間を意味しなくなりました。変数の初期化子から推測される自動型を意味するようになりました。

88
Mike Seymour

まず第一に、多くの場所で詳細に定義されているのでこれをグーグルするべきだと言います

ローカル
これらの変数は、それらを作成する特定の関数内にのみ存在します。それらは、他の機能やメインプログラムには不明です。そのため、通常はスタックを使用して実装されます。ローカル変数は、それらを作成した関数が完了すると存在しなくなります。これらは、関数が実行または呼び出されるたびに再作成されます。

グローバル
これらの変数は、プログラムを構成する任意の関数からアクセス(つまり既知)できます。これらは、メモリの場所を変数名に関連付けることで実装されます。関数が呼び出された場合、それらは再作成されません。

/* 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

グローバル変数のスコープは、宣言を慎重に配置することにより制限できます。これらは、宣言から現在のソースファイルの最後まで表示されます。

#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 */
}

静的:
静的オブジェクトは、構築されてからプログラムが終了するまで持続するオブジェクトです。そのため、スタックオブジェクトとヒープオブジェクトは除外されます。ただし、グローバルオブジェクト、名前空間スコープのオブジェクト、クラス/関数内で静的に宣言されたオブジェクト、およびファイルスコープで宣言されたオブジェクトは静的オブジェクトに含まれます。静的オブジェクトは、プログラムの実行が停止すると破棄されます。
このチュートリアルリストを参照することをお勧めします

AUTO:
C、C++

(自動変数と呼ばれます。)

コードブロック内で宣言されたすべての変数はデフォルトで自動ですが、これはautoキーワードを使用して明示的に設定できます。

Autoの代わりにストレージクラスレジスタを使用することは、コンパイラが変数をプロセッサレジスタにキャッシュするためのヒントです。参照演算子(&)を変数またはそのサブコンポーネントで使用できないようにする以外に、コンパイラはヒントを自由に無視できます。

C++では、実行が宣言の場所に達すると、自動変数のコンストラクターが呼び出されます。デストラクタは、指定されたプログラムブロックの最後に達すると呼び出されます(プログラムブロックは中括弧で囲まれます)。この機能は、ファイルを開いてから自動的に閉じる、メモリを解放するなど、リソースの割り当てと割り当て解除を管理するためによく使用されます。 SEE WIKIPEDIA

12
Freak

違いは、静的変数はそれらの変数です:関数の呼び出しごとに値を保持できるようにすることです。ただし、ローカル変数の場合、スコープはブロック/関数の有効期限までです。

例えば:

#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;
}
4
user1746468

staticは、CおよびC++のオーバーロードの多いWordです。関数のコンテキストのstatic変数は、呼び出し間で値を保持する変数です。それらはプログラムの期間中存在します。

ローカル変数は、関数の存続期間またはそれを囲むスコープが何であれ持続します。例えば:

void foo()
{
    int i, j, k;
    //initialize, do stuff
} //i, j, k fall out of scope, no longer exist

このスコーピングは、{ }ブロックで意図的に使用される場合があります。

{ 
   int i, j, k;
   //...
} //i, j, k now out of scope

グローバル変数は、プログラムの期間中存在します。

autoは、CとC++では異なります。 Cのautoは、ローカル変数を指定する(余分な)方法でした。 C++ 11では、autoを使用して、値/式のタイプを自動的に導出するようになりました。

3
Yuushi

ローカル変数は、関数の終了後、メモリ内で存在しないです。
ただし、static変数割り当てられたままプログラムの存続期間中、関数に関係なくメモリ内にあります。

さらに、あなたの質問から、static変数はclassまたは関数スコープでローカルに、namespaceまたはファイルスコープでグローバルに宣言できます。彼らは最初から最後までメモリを割り当てられます、それは遅かれ早かれ起こるただの初期化です。

3
iammilind

変数がクラス内で静的に宣言されると、その変数はそのクラスのすべてのオブジェクトの共有変数になります。つまり、変数はオブジェクトに固有のものになります。例えば: -

#include<iostream.h>
#include<conio.h>
class test
{
    void fun()
    {
        static int a=0;
        a++;
        cout<<"Value of a = "<<a<<"\n";
    }
};
void main()
{
    clrscr();
    test obj1;
    test obj2;
    test obj3;
    obj1.fun();
    obj2.fun();
    obj3.fun();
    getch();
}

このプログラムは、次の出力を生成します。-

Value of a = 1
Value of a = 2
Value of a = 3

グローバルに宣言された静的変数についても同じことが言えます。変数を外部関数void fun()として宣言すると、上記のコードは同じ出力を生成します

一方、キーワードstaticを削除し、aを非静的ローカル/グローバル変数として宣言すると、出力は次のようになります。

Value of a = 1
Value of a = 1
Value of a = 1
2
user3472599