学点C言語(34):関数-変数(auto、static、register、extern、volatile、restrict)について

5408 ワード

1.ローカル変数:
局所変数は自動変数とも呼ばれ、関数の開始、スタックの生存を宣言し、その生命は関数の戻りに伴って終了する.
#include <stdio.h>

int main(void)
{
    auto int i = 9; /*             auto;      ,        */   

    printf("%d
", i); getchar(); return 0; }

2.グローバル変数:
グローバル変数は関数の体外で宣言され、一般的に関数の前に宣言されます.各関数は使用できますが、グローバル変数はできるだけ少なく使用する必要があります.
#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; }

グローバル変数は空に初期化され、ローカル変数は値が割り当てられていない前にゴミ値になります.
#include <stdio.h>

int gi; /*      */

int main(void)
{
    int i; /*      */
    
    printf("%d, %d
", gi, i); getchar(); return 0; }

グローバル変数がローカル変数と重複する場合は、ローカル変数が使用されます.
#include <stdio.h>

int a = 111, b = 222;

int main(void)
{
    int a = 123;
    printf("%d,%d
", a, b); /* 123,222*/ getchar(); return 0; }

3.staticキーワード:
staticキーワードで修飾されたローカル変数は静的ローカル変数である.
静的ローカル変数の格納値は、グローバル変数と同様であり、それを持つ関数にのみ属するという違いがあります.空に初期化されます.
#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キーワードで修飾されたグローバル変数は静的グローバル変数である.静的グローバル変数は、そのセルを定義するためにのみ使用できる.
//    File1.c      :
static int num = 99;  /*       static           */

//  File2.c    :
#include <stdio.h>

extern int num;

int main(void)
{    
    printf("%d
", num); getchar(); return 0; }

関数が呼び出された回数を静的変数で記録します.
#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; }

4.レジスタ変数(register):
本ではレジスタ変数がスタックやスタックではなくできるだけ変数をレジスタに置くことでアクセス速度を速めると言っていますが、試してみましたが、効果は普通です.
#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; }

4.externキーワード:
外部グローバル変数を使用するにはexternで再宣言する必要があります.
externを使用しない場合は、再定義されます.
リンクフェーズでは、同じプログラムで異なるユニットのグローバル変数は共通であるため、再定義できない.
この例では、手間を省くために別のファイルには関与せず、変数をファイルの最後に置いてシミュレーションしただけである.
また、externは主に関数に用いる.
#include <stdio.h>

extern int g1;

int main(void)
{    
    extern int g2;

    printf("%d,%d
", g1,g2); getchar(); return 0; } int g1 = 77; int g2 = 88;

5.volatileキーワード:
プログラムは変数を使用する場合、特に変数を連続的に複数回使用する場合、一般的にレジスタにロードされ、直接レジスタからアクセスし、その後メモリに戻る.
ただし、この変数がメモリに戻ったときに、メモリの値が変更された場合(外部から変更された場合)はどうしますか?
このような事態を回避するために、volatileでこの変数を説明することで、変数の使用たびにメモリから直接アクセスすることを保証することができる.
しかし、これは効率に影響を与えるに違いない.幸いにもよく使われていない.
また、const volatileが同時に使用する場合、この変数は外部の修正のみを受け入れることを示す.
#include <stdio.h>

volatile int num = 123;

int main(void)
{    
    printf("%d
", num); getchar(); return 0; }

6.restrictキーワード:
restrictはvolatileとは少し反対です.しかしrestrictはポインタにすぎない.
C++Builder 2009はサポートしていないようで、しばらくテストできません.