C++ stack 영역

C++/C++ 문법 2019. 12. 17. 09:01
728x90

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이 저장되어 있음을 확인할 수 있다.

블로그 이미지

Link2Me

,