C 및 C++ 에서 변수가 어떻게 저장되는지를 예제를 통해서 알아보자.
[그림 출처] : http://myblog.opendocs.co.kr/archives/1301
전역변수 및 상수는 data 영역을 사용한다.
지역변수 앞에 static을 붙이면 전역변수가 된다.
Heap 메모리 : 힙 영역에 저장되고 지속성이 보장되나 프로그래머에의해 꼼꼼한 관리(메모리 해제)가 필요함.
stack은 LIFO(Last In First Out) 방식의 시퀀스이다.
지역변수, 매개변수는 stack 영역을 사용한다.
#include <iostream> using namespace std;
void sub(int x) { int k = 2; cout << "x = " << x << ", x 주소 : " << (uintptr_t)&x << endl; cout << "k = " << k << ", k 주소 : " << (uintptr_t)&k << endl; }
int main() { int a = 3; cout << "a = " << a << ", a 주소 : " << (uintptr_t)&a << endl; sub(a); }
|
실행결과
맨 처음에 a 주소가 할당되면서 주소값이 가장 크다는 걸 알 수 있고,
k주소값은 맨 나중에 할당되면서 주소값이 적다는 걸 알 수 있다.
여기서 int a = 3 을 static int a = 3 으로 변경해서 주소값이 어떻게 바뀌는지 확인해보라.
그리고 static int k = 2; 으로 변경해서 주소값을 확인해 보라.
sub 함수를 호출할 때 사용하는 주소가 어떻게 다른지 확인해보자.
#include <iostream> using namespace std;
void sub(int x) { // int x 는 매개변수 cout << "x = " << x << ", x 주소 : " << (uintptr_t)&x << endl; }
int main() { sub(1); sub(3); sub(5); }
|
실행결과 → 매개변수는 모두 동일한 메모리 주소를 사용
함수가 매개변수 주소를 할당하고, 반납하고, 다시 같은 주소에 값을 할당하고, 반납한다는 걸 알 수 있다.
재귀함수 호출을 해 봄으로써 변수가 어떻게 저장되는지 확인해보자.
#include <iostream> using namespace std;
void sub(int x) { cout << "x = " << x << ", x 주소 : " << (uintptr_t)&x << endl; if(x > 1) sub(x - 1); }
int main() { sub(1); sub(3); sub(5); }
|
실행결과
주소가 어떻게 할당되는지 확인해 보면,
sub(1)을 실행시 매개변수 1에 대한 주소값을 사용하고, 주소를 반납한다.
sub(3)을 실행시 매개변수 3에 대한 주소값이 sub(1) 실행시의 주소값과 같음을 확인할 수 있다.
재귀함수 sub(2)의 주소는 처음할당된 주소값보다 작음을 알 수 있다.
재귀함수 sub(1)의 주소는 더 적은 값임을 알 수 있다.
sub(5)을 실행시 매개변수 5에 대한 주소값, 재귀함수 sub(4), sub(3), sub(2), sub(1)에 대한 주소값을 확인해보면,
맨 처음에 할당된 주소값이 가장 크고, 위로 갈 수록 주소값이 점점 적어지는 걸 확인할 수 있다.
예제1. 출처 : https://www.softwaretestinghelp.com/stack-in-cpp/
#include<iostream> using namespace std;
#define MAX 1000 //max size for stack
class Stack { int top; public: int myStack[MAX]; //stack array
Stack() { top = -1; } bool push(int x); int pop(); bool isEmpty(); };
//pushes element on to the stack bool Stack::push(int item) { if (top >= (MAX - 1)) { cout << "Stack Overflow!!!"; return false; } else { myStack[++top] = item; cout << item << endl; return true; } }
//removes or pops elements out of the stack int Stack::pop() { if (top < 0) { cout << "Stack Underflow!!"; return 0; } else { int item = myStack[top--]; return item; } }
//check if stack is empty bool Stack::isEmpty() { return (top < 0); }
// main program to demonstrate stack functions int main() { class Stack stack; cout << "The Stack Push " << endl; stack.push(10); // 스택에 등록 stack.push(20); stack.push(30);
cout << endl << "The Stack Pop : " << endl; while (!stack.isEmpty()) { // 스택이 비어 있지 않는 동안 cout << stack.pop() << endl; } return 0; }
|
예제2.
#include <iostream> #include <vector> #include <stack> using namespace std;
int main() {
stack<int> st; // default 는 deque 컨테이너 사용 //stack<int, vector<int>> st; vector 컨테이너를 이용하여 stack 컨테이너 생성
st.push(10); // stack에 등록 st.push(20); st.push(30);
cout << st.top() << endl; // stack 제일 위의 요소 가져오기 st.pop(); // 스택 제일 위의 요소 제거 cout << st.top() << endl; st.pop(); cout << st.top() << endl; st.pop();
if (st.empty()) // stack이 비었는지 확인 cout << "stack에 데이터 없음" << endl;
return 0; } |
실행해보면, stack 에 저장된 순서가 10, 20, 30 으로 맨 아래부터 저장되어 맨 위에 30이 저장되어 있음을 확인할 수 있다.