C에서 변수가 선언되면, 각 변수는 적용되는 영역을 갖는다. 그 영역은 국지적으로 사용될 수도 있고, 전역적으로 사용될 수도 있다.

기본적으로 블록 내에서 선언된 변수들은 블록 내부에서 로컬리 사용된다.
블록은 { } 으로 감싸지고, 각 블록은 블록마다 변수를 선언할 수 있다.

ANSI C (C89) 에서 변수의 선언은 블록의 첫부분에서 이루어져야한다. C99 부터는 중간에 선언해도 된다.

블록은 블록내에 또 잡을수 있으므로 이런 방식을 이용하면 함수 중간에 원하는 위치에서 변수를 선언할 수 있다.

아래 왼쪽 코드는 ANSI C (C89) 에서 에러가 난다. 중간에 변수의 선언이 이루어졌기 때문이다. 반면 오른쪽의 코드는 문제가 없다.

int main(void)                                              int main(void)
{                                                              {
      int a=0;                                                     int a=0;
      a++;                                                         a++;
                                                                    {
     int b;                                                             int b;
     ...                                                                 ...
                                                                    }
}                                                              }


그런데 이때, 변수에 대한 scopre rule 은 블록내부이므로, 중간에 새 블록으로 감싸고 선언한 변수는 그 블록을 닫기 전까지만 유효하다는 것에 유의해야한다.

---------------------------------------------------------------------------------------------------

C의 모든 변수와 함수는 데이터 타입 이외에도, 외에도 기억영역 클래스라는 구분을 갖는다. 이것은 적용영역하고도 관련이 있다.

기억영역 클래스 auto, extern, register, static 에 대해서 알아보자.
이것들은 동시에 각 클래스에 대응되는 키워드들이다.

사용형식은 memory_class type identifier ;  이다.
이때 타입은 생략될 수 있으며, 생략시 데이터타입의 디폴트인 int 로 인식된다.

---------------------------------------------------------------------------------------------------

auto 자동변수

함수 내부에서 선언된 변수는 디폴트 로 기억영역 클래스 auto 를 갖는다.

블록 안으로 들어갈때, 시스템은 auto 변수들을 위해 메모리를 할당하고, 블록내에서 로컬리 사용된 변수들은 블록을 벗어날때 메모리를 반납한다. 이후에 블록에 다시 들어가게 되면, 다시 메모리를 할당하지만 이전의 변수값은 알수가 없다.

블록 내에서 디폴트가 auto 이므로, 블록내에서  int a ;auto int a; 와 같다.

---------------------------------------------------------------------------------------------------

extern 외부변수

함수 외부에서 선언된 변수는 디폴트로 extern 이 되고, 글로벌리 사용된다.
가령, 함수밖에서 int a; extern int a; 와 같다. 할당된 메모리는 프로그램이 종료될 때 반환된다.

함수 내부에서 변수 선언시 데이터 타입앞에 키워드 extern 을 사용하면, 그 변수는 그 함수 밖에 이미 extern 으로 선언되어 있는 변수라는 뜻이다. 즉, 외부에서 이 변수를 찾아서 사용해라 라는 의미 정도 된다.

여기서 함수 외부라고 하는 것은 연관된 다른 파일도 포함된다.

함수 내부에서 선언된 변수들은 로컬리 사용되기 때문에, 함수간에 그 변수값을 전달하려면 리턴값으로 보내던지 해야한다. 반면, extern 변수들은 그것과 상관없이 함수간에 값을 전달할 수 있다.

만약, extern 변수가 외부에 있는 상황에서 같은 식별자를 사용하여 함수 내부에서 auto로 변수가 또 선언된다면, 그 함수내에서는 로컬변수가 우선순위가 높으며, 외부변수는 그 내에서는 숨겨진다.


모든 함수들은 선언시에 이미 블록 밖에 있기 때문에 extern 이다.

가령, int f(int ); 라는 프로토타입은 extern int f(int); 와 같다.

---------------------------------------------------------------------------------------------------

register 레지스터변수

컴파일러에게 register 를 사용하도록 권고한다. 단지 권고일뿐 할당받지 못하면 auto 이다. 다시말해, 디폴트가 extern 인 경우는 register 가 될수없다.

레지스터로 많이 선택되는 변수는 루프변수와 접근이 잦은 함수의 퍼레미터이다.

주의: 레지스터 변수는 포인트할 수 없음.

---------------------------------------------------------------------------------------------------

static 정적변수

static 은  파일내에서, 기본적으로, 변수값을 소멸시키지 않고 고정적 지위를 주어서 글로벌리 사용하는것이 기본 목적이다.
따라서, 스코프는 해당 파일내에서, 선언된 이후이다. 한번 선언해 놓은 static 변수는 다시 선언시에 선언이 먹히지 않는다.
그래서 'static' 이라는 표현을 쓴다. 한번 선언하면, 쭈욱~ 유지된다.

주의할점은, static 파일 전체에 걸쳐, 어떠한 지위를 갖기 때문에, 해당 변수가 선언되기 전이라고 하더라도,
해당 파일내의 다른 함수가 그 변수명을 사용할 수 없게 된다.

블럭의 입장에서, 블럭 내부에서 선언된 static 은 static auto 로, 외부에서 선언된 static 은 static extern 이 된다.
static 은 블럭을 빠져나가도 해당 파일내에서는 그 값을 유지한다. 물론, 블럭 안에서 다시 호출해도 여전히 현재 저장된 값을 쓴다.


static auto                                                                    static extern

{                                                                static int a;
     static int a;                                              ...
     ...                                                         {
}                                                                       ...
                                                                 }


함수도 변수와 마찬가지로 데이터 타입을 갖듯이 ( =리턴타입) 함수도 기억영역 클래스를 갖는다고 했다.
특히, 함수는 항상 외부에서 선언되므로, extern 이었고, 따라서, 함수에 static 을 쓰면, 당연히 static external 이된다.

즉, 다른파일에서는 그 함수를 쓸수가 없다.

----------------------------------------------------------------------------------------------

예.

void f(void)
{
      static int cnt = 0 ;
      ++cnt;

      if(cnt%2 == 0)
            ...
     
else
           ...
}

이 함수가 선언될때, cnt 라는 static 변수가 선언되므로, cnt 라는 변수는 파일전체에 걸쳐서 고정적인 지위를 갖는다.
단, 스코프는 선언된 이후부터 이다.

이 함수를 호출하게 되면, 첫 호출시 cnt 라는 static 변수가 선언되고, 0 으로 초기화 된다. 그러나 이후에 이 함수가 호출될때
이 선언문은 먹히지 않는다.

함수의 호출마다 ++cnt 가 실행되고, 블럭을 벗어나도 cnt 값이 유지된다.

함수내의 if 문에서 cnt 의 패리티에 따라 기능이 다르게 만들어 놓으면, 이 함수는 호출 횟수의 홀짝에 따라 다른 기능의 함수가 된다.