변수의 종류 파악하기
지금까지 변수와 배열을 사용했던 곳은 main() 함수 안이거나 직접 만든 함수 안이었다. 그러나 변수와 배열의 선언은 반드시 함수 안에서만 해야 하는 것은 아니다. 변수와 배열은 함수 바깥에서도 선언 가능하기 때문이다.
함수 안에 선언한 변수를 지역 변수(local variable),
함수 바깥에 선언한 변수를 전역 변수(global variable) 이라고 부른다.
스코프의 원리 이해하기
지역 변수와 전역변수는 어떤 차이점이 있을까?
먼저 지역 변수(local)의 경우,
선언된 함수 안에서만 사용할 수 있다.
반면 전역 변수(global)는,
어떠한 함수에서도 사용할 수 있다.
밑의 그림은 각각의 변수의 유효 범위를 그림으로 표현한 것이다.
이러한 변수 이름의 통용범위를 가리켜 스코프(scope)라고 부른다.
선언 위치 | 스코프 | |
지역 변수 | 함수 안 | 변수가 선언된 곳에서부터 함수가 끝나는 위치까지 사용 가능 |
전역 변수 | 함수 바깥 | 어떠한 함수에서도 사용 가능 |
지역 변수끼리 이름이 겹칠 경우
함수 안에 선언되는 변수 이름은 중복해서 사용할 수 없다.
그러나 다른 함수 안에 선언된 지역 변수들의 이름은 겹쳐도 된다.
전역 변수와 이름이 겹칠 경우에는?
전역 변수와 지역 변수의 이름은 같아도 상관없다!
이처럼 전역 변수와 지역 변수가 a 로 이름이 중복될 때에,
main() 함수 안에 'a++' 같은 코드를 작성하면 지역 변수 a를 사용한다는 뜻이 된다.
그리고 func() 함수 안에서 지역 변수의 이름 때문에 전역 변수의 이름이 숨겨지는 것에도 주의할 것!
이 상태에서 지역 변수와 이름이 중복되는 전역 변수를 사용하려면 :: a++ 처럼 범위 해결 연산자 (::)를 사용해야 한다.
변수의 기억 수명
(1) 변수를 선언하면 먼저 값을 저장하기 위한 상자가 메모리에 마련된다. 이 상태를 메모리가 확보되었다고 부른다.
(2) 그 후 변수는 값의 저장 및 출력에 이용되고
(3) 마지막에 상자가 파괴됨과 동시에 상자가 점유하고 있던 메모리는 다른 용도로 사용된다. 이 상태를 메모리가 해제되었다고 부른다.
이 과정, 변수를 담는 상자가 만들어진 후 파괴될 때까지의 기간을 기억 수명이라고 부른다.
지역 변수는 일반적으로 다음 규칙에 따라 만들어지고 소멸한다.
(1) 함수 안에 선언될 때, 변수 상자가 메모리에 준비된다.
(2) 함수가 종료되는 시점에 상자가 파괴됨에 따라, 그 상자가 점유하던 메모리는 다른 용도로 사용된다.
즉, 일반적인 지역 변수는 선언된 후 함수가 종료될 때까지만 값을 저장할 수 있는 것이다.
반면, 전역 변수는 다음 규칙에 따라 만들어지고 소멸한다.
(1) 프로그램 본체의 처리가 시작되기 전, 단 한번만 메모리를 확보한다.
(2) 프로그램 종료 시 메모리에서 해제시킨다.
즉, 전역 변수는 프로그램이 시작되어서 종료될 때까지 계속해서 값을 저장할 수 있는 것이다.
static을 붙이는 경우
지역 변수는 속하는 함수가 종료될 때 파괴되는 것이 일반적이다. 그러나, 지역 변수에 static 키워드를 붙이게 되면, 전역 변수와 같은 기억수명을 가지게 되어 프로그램이 끝날 때까지 파괴되지 않게 된다. 이러한 지역 변수를 가리켜, 정적 수명을 가진 지역 변수라고 부른다. static은 기억 클래스 지정자(storage class identifier)라고 한다.
기억 클래스 | 기억 수명 | |
지역 수명 | (자동) | 선언된 후부터 함수가 끝날 때까지(자동) |
static | 프로그램의 실행을 준비할 때부터 프로그램이 종료될 때까지(정적) | |
전역 변수 | 프로그램의 실행을 준비할 때부터 프로그램이 종료될 때까지(정적) |
그리고, 변수의 초기화 코드를 작성하지 않았을 경우 전역 변수와 static 지역 변수는 자동으로 0으로 초기화된다.
반면에 초기화 작업을 하지 않은 지역 변수의 초기값은 정해져 있지 않다.
지역 변수를 가리키는 포인터와 리턴값
함수 안에서 포인터를 사용할 때는 주의해야 할 점들이 있다. 다음 코드를 보면,
이 코드의 func()함수는 func 함수 안에 선언한 지역 변수 a를 가리키는 포인터(pA)를 리턴하고 있다.
그러나, func() 함수가 종료될 때, 지역 변수 a도 함께 삭제되어 버린다. 따라서 호출자에게 리턴한 변수 a의 주소값은 아무런 의미가 없는 것이다! 결과적으로, pRes는 의미없는 포인터가 되어 버린다.
이런 의미없는 포인터를 사용해서 프로그램을 작성하면 에러를 발생시킬 수 있으니, 리턴 값은 신중하게 골라야 한다. 반면에 다음 리턴값은 사용할 수 있다.
이 코드 또한 함수 안에서 선언된 지역 변수를 가리키는 포인터를 리턴한다. 그러나 이 변수 a는 static을 붙인 정적 변수이기에 함수가 종료된 후에도 존재한다. 따라서 이 변수를 가리키는 포인터는 호출한 곳에서도 사용할 수 있게 된다!
같은 이유로 함수 안에서는 일반 로컬 변수의 레퍼런스를 리턴할 수 없다. 레퍼런스는 변수의 별명에 지나지 않기 때문이다. 변수가 파괴되었다면 레퍼런스 또한 의미가 사라진다.
일반 지역 변수를 가리키는 포인터는 리턴 값으로 사용하면 안된다.
'C++ 코딩 > C++ 기초개념' 카테고리의 다른 글
<C++ 기초> 식과 연산자, 연산자의 종류와 우선순위 (0) | 2021.02.23 |
---|---|
<C++ 기초> 동적배열, sti vector, 멤버함수 (0) | 2021.02.18 |
<C++ 기초> typedef, 열거형 enum (0) | 2021.02.16 |
<C++ 기초> 문자열 조작하기 -char[], string (0) | 2021.02.15 |
<C++ 기초> 메모리 동적 확보, 배열의 동적인 확보 (0) | 2021.02.14 |
<C++ 기초> 메모리 구조 힙, 스택, 데이터, 코드 (0) | 2021.02.09 |
<C++ 기초> 배열에 대한 이해, 문자열과 배열, char 02.08 (0) | 2021.02.08 |
<C++ 기초> 포인터와 레퍼런스(* , &) 02.04 (0) | 2021.02.04 |