#include <stdio.h>
// <변수의 종류>
// 1. 지역변수 : 스택 영역을 사용함
// 2. 전역변수 : 데이터 영역을 사용함.
// 3. 정적변수 (static) : 데이터 영역을 사용함.
// 4. 외부변수 (extern) : 데이터 영역을 사용함.
// <메모리 영역> - OS가 프로그램이 실행될 때 부여하는 메모리 영역.
// OS마다 다르고, 디테일하게는 더욱 세분화하여 분류할 수 있지만 대표적으로 아래의 4가지로 분류된다.
// 1. 스택영역 : 운영 체제가 알아서 크기를 정한다. 대부분 1MB 정도 크기를 할당하면 충분하다.
// 프로그래머가 직접 그 할당 크기를 조절할 수 있긴 하지만 거의 건드릴 일이 없다.
// 함수의 설계도 대로 실행되는 실행흐름의 메모리가 존재한다. (실제 실행되는 코드를 메모리에 올린다)
// 이러한 메모리는 실행흐름의 시작과 함께 할당되었다가 실행 흐름이 종료되면 (함수가 리턴되면)
// 메모리에서 삭제된다. 스택 영역은 이러한 FLOW에 따라서 가변적으로 메모리가 변한다.
// 2. 데이터 영역 : 프로그램이 최초로 실행될 때(메인 함수가 호출될 때) 생성되는 영역.
// 즉 전역 변수들은 프로그램의 시작과 동시에 할당되어 메모리를 차지하게 된다.
// 또한 프로그램이 실행되는 동안 계속 메모리에 상주하다가 프로그램이 종료되면 메모리에서 해제된다.
// 즉, 전역 변수는 프로그램이 실행되는 내내 존재한다.
// 3. 읽기 전용(코드, ROM)
// : 상수, 함수의 설계도가 들어있다. exe 파일 정도의 크기를 가진다.
// 4. 힙 영역
// 전역 변수
// 전역변수는 스택 메모리 영역를 사용하는 지역 변수와 달리 데이터 영역을 사용한다.
int g_i = 0; // Data 영역
void Test()
{
int i = 0; // 지역변수 선언
++i;
}
void Test2()
{
++g_i;
}
int main()
{
// 지역 변수
// 연달아 함수를 호출해도 i가 계속 증가하지는 않는다.
// test 함수가 호출될 때 test 함수의 스택 메모리에 지역 변수 i가 생성된다.
// 이 변수는 함수가 종료될 때 스택 메모리에서 해제되면서 반환되므로
// 또 다시 Test() 함수를 호출하더라도 또 다시 0으로 초기화 된다.
Test(); // 함수 호출
Test();
Test();
// 아래 함수의 경우 전역 변수 g_i가 1씩 증가하도록 되어 있다.
// 전역 변수는 프로그램이 실행되는 동안 계속해서 데이터 영역 메모리에 남아있기 때문에
// 할당된 변수와 값이 보존된다. 따라서 아래처럼 함수를 3번 호출하면
// g_i의 호출 1번당 1씩 증가하여 최종값이 3이 된다.
Test2();
Test2();
Test2();
return 0;
}
- 전역 변수
특정 블록 스코프에 속하지 않고 소스 파일 전체에서 접근(파일 스코프)할 수 있는 형태로 선언 및 정의된 변수이다.
스택 메모리 영역을 사용하는 지역변수와 달리 전역 변수는 데이터 영역을 사용해 데이터를 저장한다.
그렇기 때문에 전역 변수는 지역 변수와 다른 특징을 가지고 있다.
전역 변수는 main() 함수가 실행되기 전 프로그램이 최초 실행 될 때 부터 이미 존재하는 것이며 프로그램이 끝날 때까지 사라지지 않고 데이터 영역에 저장한 메모리를 유지한다.
따라서 전역 변수에 저장한 값은 지역 변수와 달리 함수를 넘나들어 접근할 수 있다. - 메인 함수에서 선언한 변수를 다른 함수에서 사용할 수 있을까?
둘의 함수 영역이 다르므로 불가능하다. 아래의 코드처럼 test 함수를 호출하면,
이 test 함수 스택 영역에는 main 함수 스택 영역에 존재하는 a가 없으므로 컴파일 오류가 발생한다.
void Test()
{
++g_i;
a = 100;
}
int main()
{
int a = 0;
g_i = 0; // 전역변수인 g_i의 경우에는 메인 함수를 비롯한 어느 함수에서나 호출이 가능하다.
// 함수의 스택 영역이 아닌 데이터 영역에 저장되어 있기 때문이다.
}
전역 변수는 별도의 매개변수나 반환 자료형 같은 형식을 이용하지 않고도 한 정보를 쉽게 공유할 수 있게 한다.
이처럼 전역 변수는 매우 편리해 보이는 특징을 가지고 있지만, 설계적으로는 매우 부적절하다.
그 이유는 서로 떨어져 독립적이어야 할 두 코드를 하나로 묶어주는 역할을 하기 때문이다.
우리가 프로그래밍에서 UI나 기능들을 함수 단위로 나눠서 설계하는 이유는 코드의 독립성을 유지하기 위해서다.
따로 떨어져 독립적인 코드에서 문제가 발생하면 그 독립적인 하나만 수정 보완하는 것으로 문제를 해결할 수 있기 때문이다.
그러나 전역 변수를 오남용하면 서로 독립적이여야 하는 둘을 전역 변수를 매개로 하나로 묶어버릴 수 있다.
즉, 서로 불필요한 의존 관계가 형성 되는 것이다.
좋은 설계란 프로그램을 적절한 단위 요소로 나누고 각 요소가 다른 요소의 변화에 영향을 받지 않도록 의존성을 최대한 낮추는 것이다.
그렇게 해서 테스트 하기도 좋고 유지보수 하기도 좋게 만들어 생산성을 향상시키도록 해야 한다.
하지만 전역 변수를 사용하는 것 자체가 나쁜 것은 아니고, 전역 변수를 아예 쓰지 않고 프로그램을 만들 수도 없다.
따라서 전역 변수는 꼭 필요할 때만 사용하도록 하고, 전역 변수의 이름 앞에는 'g_' 같은 전치사를 쓰는 것이 좋다.
(EX. g_nInput)
이렇게 하면 변수의 이름만 봐도 이것이 전역 변수라고 짐작할 수 있기 때문이다.
- 전역 변수와 식별자 검색 순서
변수의 이름은 식별자로 사용 된다.
따라서 통용 범위가 같은 내부에 이름이 같은 두 개의 변수가 있을 수 없다.
전역 변수와 지역 변수가 서로 이름이 중복되는 경우 지역변수가 우선한다.
구체적으로 C언어에서 변수에 대한 식별자를 검색하는 순서는 다음과 같다.
1. 가장 최근에 형성된 (가장 아래쪽) 스코프에 속한 지역변수
2. 현재 블록 스코프의 외부를 감싸고 있는 상위 스코프 (최대 함수 몸체까지 검색)
3. 파일 스코프 (전역변수)
'C,C++ > [강의] 어소트락 C++' 카테고리의 다른 글
정적 변수/외부 변수 (0) | 2023.01.04 |
---|---|
분할 구현 (0) | 2023.01.01 |
구조체 (0) | 2022.12.13 |
배열 (0) | 2022.12.12 |
함수와 재귀함수 (0) | 2022.11.28 |