32. 메모리 관리와 함수
32.1. 메모리 모델에 대하여
볼랜드사의 컴파일러는 메모리 모델이라는 것을 제공합니다. 메모리 모델이란 메모리 안에서 프로그램을 어떻게 실행시킬 것인지를 결정하는 메모리관리의 모델이라고 보시면 됩니다. 메모리 모델에 관해서는 어셈블리어 공부를 하지 않은 이상 쉽게 이해하기 힘든 부분이므로 메모리모델이라는 것이 있다 하는 정도만 알고 넘어가시면 됩니다. 메모리모델을 다루는 문제는 기초과정에서 다룰 문제가 아니므로 다음 기회에 다루도록 하겠습니다.
또한 도스에서는 메모리 모델을 사용하지만, 윈도용 프로그램은 도스와는 다른 메모리 모델을 가지고 있습니다. 때문에 윈도에서는 메모리 모델이라는 이름을 사용하지 않고 옵션을 통해서 조정합니다.
일단 터보C에서 제공하는 메모리 모델 6가지를 간단하게 정리해두었으니 참고하시기 바랍니다. 실제로 메모리 모델을 사용하는 경우는 거의 없지만 참고사항으로 정리해두었습니다. 메모리 모델은 컴파일러 옵션에서 결정할 수 있다는 것만 기억하시기 바랍니다. 메모리 모델은 초보자에게는 너무 골치 아픈 이야기이므로 이번 장은 읽지 않고 지나가셔도 좋습니다.
32.1.1. 초소형 모델(tiny model)
초소형 모델은 확장자가 com인 파일을 만들 때 사용합니다.
가장 작은 메모리 모델입니다. 이 모델에서는 모든 세그먼트 레지스터가 동일한 번지에 존재합니다. 그래서 항상 CS와 DS, SS, ES가 같은 번지를 가진다고 보시면 됩니다. CS DS니 하는 말들이 무엇을 뜻하는지 이해하실 필요는 없습니다. 그냥 그런 것이 있나보다 하고 넘어가시면 됩니다.
이 모델의 특징만 말씀드리면 64KByte의 메모리 공간만이 할당된다는 점입니다. 그래서 640KByte의 나머지 메모리 공간은 제어할 수 없습니다. 또 모든 포인터는 근거리 포인터로 내정됩니다. 역시 무슨 소리인지 잘 모르시겠죠?
딱 하나만 알고 계시면 됩니다. 이 모델만이 확장자가 com인 *.COM 파일을 만들 수 있다는 것입니다. 그러니까 다른 메모리 모델로 설정해놓고 프로그램을 만들면 모두 EXE 파일로만 만들어진다는 것입니다. com파일을 만들려면 exe2bin.exe이라는 프로그램을 사용하거나 링크할 때 /t 옵션을 지정하는 방법을 이용합니다. com파일을 만들 수 있기 때문에 램상주 프로그램을 만들 때 주로 사용하는 메모리모델입니다.
세그먼트란 메모리를 일정 크기로 나눈 블럭으로 64KB를 단위로 삼습니다.
이쯤에서 세그먼트에 대해서는 약간의 설명이 필요할 것 같군요. 세그먼트란 메모리 관리의 효율성을 위해서 메모리를 일정 크기로 나눈 블럭을 말합니다. 그러니까 하나의 논리적 단위가 되는 것입니다.
8086 CPU는 20비트, 즉 최대 1MByte의 번지 공간(address space)을 가집니다. 그러나 1메가를 한 번에 제어하지는 못하고 한 번에 64KByte까지만 제어할 수 있도록 되어 있습니다. 그 이유는 메모리 관리상의 효율과 처리 속도의 증대를 위해서입니다.
그러나 원래는 8비트급 CPU인 8080과의 상위 호환성을 유지하기 위해서 64KByte의 세그먼트 개념이 도입된 것으로 볼 수 있습니다. 즉 IBM PC 이전에 사용하던 8비트 컴퓨터인 애플 컴퓨터 등에서 64KByte의 메모리를 이용했기 때문에 프로그램의 크기가 64KByte를 넘지 못했던 것입니다. 애플 시절에는 프로그램의 크기를 64Kbyte 이내에서 만들었습니다. 이 때문에 실행파일의 크기가 64KByte 이내로 정해졌고, 프로그램이 실행되면서 관리할 메모리의 크기 역시 64KByte면 충분했던 것입니다. 이런 이유로 메모리의 세그먼트 단위가 64KByte가 된 것입니다.
8086 CPU는 8080와 8085를 바탕으로 미국의 인텔사가 개발한 CPU입니다. 이 CPU는 데이터버스를 16비트 폭으로 확장하여 2바이트 단위의 워드 단위 연산을 하므로 속도가 빠릅니다. 그리고 1메가(00000H ~ FFFFFH)의 넓은 메모리 공간을 가질 수 있습니다. 또한 번지 지정방식이 강화돤 CPU입니다. 그러나 1메가바이트의 메모리를 한꺼번에 전부 사용할 수 는 없습니다. 그래서 1MByte의 공간을 64KByte의 번지 공간으로 나누어 효과적으로 제어하기 위해 "세그먼트(segment)"라는 새로운 개념이 도입됩니다. 즉 세그먼트는 1MByte의 메모리를 64KByte씩 잘라 놓은 덩어리로 보셔도 됩니다.
8086 CPU는 CPU 안의 주소를 구분해놓은 레지스터를 가집니다.
8086 CPU는 몇 가지 레지스터를 가집니다. 레지스터는 CPU를 일종의 번지에 의해서 구분해놓은 단위라고 보시면 됩니다. 쉽게 말하면 CPU 안의 주소입니다. 레지스터는 플래그 레지스터, 주레지스터, 포인터 인덱스 레지스터, 세그먼트 레지스터로 나눕니다.
주레지스터는 A, B, C, D라는 이름에 X를 붙여 축적연산을 하는 AX(어큐뮬레이터 레지스터), 번지 포인트용인 BX(베이스 레지스터), 카운터용인 CX(카운트 레지스터), 데이터용으로 쓰는 DX(데이터 레지스터)로 나눕니다. 이들은 다시 상위 8비트 길이를 사용할 때는 H를 붙이고, 하위 8비트를 사용할 때는 L을 붙여서 AH, AL, BH, BL, CH, CL, DH, DL로 구분합니다. 이 레지스터를 자유롭게 제어하려면 어셈블리어를 배워야 하므로, 이 글을 읽을 때는 AX나 AH가 무엇을 가리키는 말인지 알고 계시면 충분합니다.
그리고 포인터 인덱스 레지스터에는 SP(스택 포인터), BP(베이스 포인터), SI(소스 인덱스), DI(데스티네이션 인덱스), 인스트럭션 포인터(IP)로 구분합니다. 인스트럭션 포인터는 명령을 메모리에서 읽어내기 위해서 사용하며, 스택 포인터는 스택의 최고 윗 번지를 구하기 위해 사용합니다. SI, DI, BP는 메모리 내의 데이터를 가리키기 위해서 사용합니다.
그리고 우리가 자주 접하게 될 세그먼트 레지스터로는 CS, DS, ES, SS 등이 있습니다. 즉 4개의 특정 64 세그먼트를 각각 코드, 데이터, 스택, 여분(엑스트라) 세그먼트라고 부릅니다. 즉 64x4=256KByte이므로 최대 256KByte의 공간을 직접 참조할 수가 있고 그 외의 공간은 직접 참조할 수가 없습니다.
코드 세그먼트는 기계어 명령(machine instruction)이 놓여 있는 곳이고 데이터 세그먼트는 각종 데이터(변수 등)이 놓이는 곳이고, 스택 세그먼트는 물론 스택입니다. 그 밖에 여분 세그먼트는 추가적인 데이터가 놓이는 곳입니다.
이들 세그먼트는 각각 CS, DS, SS, ES라는 16비트의 세그먼트 레지스터에 의해 그 시작 번지가 결정됩니다. 즉 세그먼트 레지스터 CS, DS, SS, ES는 이들 세그먼트 레지스터의 선두번지를 지시하는 낱말입니다.
메모리를 참조할 때는 세그먼트 값과 오프셋 값을 사용합니다.
그런데 이들 메모리를 참조할 때는 물리번지를 사용하지 않고 세그먼트 값과 오프셋 값을 이용해서 참조합니다. 그 까닭은 세그먼트 레지스터는 16비트의 길이를 가지기 때문에 20비트 길이인 번지값을 다 기록할 수 없기 때문입니다. 그래서 하위 4 비트를 삭제하여 저장합니다. 즉 10000H라는 번지는 16이라는 숫자의 단위인 2번째 자리를 생략하고 1000H라고 저장하는 것입니다. 따라서 세그먼트번지는 2의 4제곱인 16칸 만큼의 간격을 두고 가리키게 됩니다. 즉 각 세그먼트 사이는 16번지의 차이가 생기는 셈입니다.
오프셋값은 세그먼트 번지로부터의 간격을 말합니다. 즉 오프셋값이 3000H라고 하면 시작번지로부터 3000번지 뒤의 번지를 가리키는 셈입니다. 이럴 경우 시작번지가 1000H고 오프셋값이 3000H일 경우 1000+3000=4000H가 번지값이 되는 것이 아닙니다. 시작번지 1000H는 4비트를 잘라낸 것이므로 16번지에 해당하는 자리수를 하나 더 채워주어야 합니다. 즉 1000H는 10000H로 바꾼 다음에 계산해야 합니다. 따라서 시작번지가 1000H이고, 오프셋값이 3000H라면 10000H+3000H=13000H가 됩니다. 즉 13000번지가 실질적인 물리번지가 되는 것입니다.
번지를 참조하는 방법이나 절대번지를 구하는 방법은 고급과정에서 자세하게 배울 것이므로 초급과정인 이 책에서는 그저 세그먼트나 오프셋이 이런 개념을 가지고 있구나 하는 정도만 말씀드리고 끝내겠습니다.
**요약: 메모리를 어떻게 관리하느냐에 따라서 메모리모델을 나누어 프로그램을 만드는데 초소형모델은 64KByte 이하의 작은 실행파일을 만들 때 사용하는 메모리 모델입니다. 확장자가 com인 파일은 초소형 모델에서만 만들 수 있습니다. 그리고 세그먼트란 64KByte씩 나눈 메모리 공간의 한 단위(블럭)을 말하며, 오프셋값은 세그먼트 번지로부터의 상대적인 거리를 가리키는 번지값입니다.
32.1.2. 소형 모델(small model)
터보C에서는 별도의 기본적으로 소형 모델로 프로그램을 컴파일합니다.
이 모델에서는 DS와 SS, ES는 같지만 DS만 다릅니다. 달리 말해서 세그먼트들이 분리된다는 이야기입니다. 달리 말한다는 것이 더 어려운 이야기가 되었군요. 더 어렵게 말씀드리면 코드영역과 스택영역이 분리되기 때문에 자료들이 서로 침범하지 않게 된다는 말인데 꼭 기억해두실 내용은 하나 뿐입니다.
터보C에서는 별도의 컴파일러 옵션을 지정하지 않는 경우 소형 모델을 기본 메모리 모델로 설정한다는 점입니다. 즉 터보C를 설치한 후에 아무런 옵션의 변경 없이 프로그램을 제작했다면 소형모델로 프로그램이 만들어진다는 점입니다. 이 말은 크기가 크지 않은 프로그램은 대부분 소형 모델로 만든다는 뜻입니다.
**요약: 소형모델은 터보C에서 기본적으로 설정한 메모리 모델로 크기가 크지 않은 프로그램을 만들 때 사용합니다.
32.1.3. 중형 모델(medium model)
중형 모델로 만든 프로그램은 64Kbyte 이상의 크기를 가진 자료는 불러올 수 없습니다.
이 모델에서는 함수 포인터가 원거리 포인터로 내정되고 데이터포인터는 근거리 포인터로 내정됩니다. 그래서 함수는 64KByte의 크기를 넘어갈 수 있지만 자료는 64KByte의 공간을 넘어갈 수 없습니다. 자료가 64KByte를 넘어갈 수 없다는 것이 무슨 말일까요? 가장 쉽게 말하자면 배열이나 변수에 저장할 수 있는 자료의 양이 64KByte 이상은 저장할 수 없다는 이야기입니다.
예를 들어서 문서파일에서 문서파일을 불러와서 변수에 저장해서 편집한다고 합시다. 이럴 경우에 변수에서 다룰 수 있는 자료의 크기가 64KByte밖에 안되므로 64KByte가 넘는 큰 문서파일일 경우에는 읽어오지 못한다는 문제가 생기는 겁니다. 즉 뒷부분을 자르고 불러와야 합니다.
게임 등을 만들 때는 화면을 저장하는 기술을 많이 사용하는데 이럴 경우에는 한 변수나 배열에 64KByte 이상의 자료를 담아야 합니다. 그래서 그때는 중형모델이 아니라 대형모델을 많이 사용합니다.
**요약: 중형 모델은 함수 포인터는 원거리 포인터를 사용하고 데이터포인터를 근거리 포인터를 사용하므로 자료는 64Kbyte 이상의 크기로 저장될 수 없습니다.
32.1.4. 중소형 모델(compact model)
이 모델은 중형 모델과는 반대로 데이터 포인터는 원거리 포인터로 내정되고 함수 포인터는 근거리 포인터로 내정됩니다. 그리고 각각의 세그먼트 들은 독립적으로 존재하며 서로 영역을 침범하지 않습니다. 데이터를 64KByte 이상 다룰 수 있기 때문에 덩치가 큰 자료를 다루는 프로그램에 많이 이용하는 모델입니다.
32.1.5. 대형 모델(large model)
대형 모델은 64KByte 이상인 exe파일을 만들 때 사용합니다.
이 모델은 함수 포인터와 데이터 포인터가 모두 원거리 포인터로 내정되어 컴파일됩니다. 복잡한 이야기 생략하고 결론만 말씀드리면 이 프로그램은 덩치가 큰 프로그램에 사용합니다. 쉽게 말해서 프로그램의 크기가 64KByte 이상인 *.exe 파일들은 대부분 이 모델로 컴파일되었다고 보시면 됩니다.
그러니까 우리가 일반적으로 사용하는 대부분의 프로그램은 대형모델에서 컴파일합니다. 그리고 앞으로 우리가 게임을 만들거나 조금 복잡한 프로그램을 만들 때도 대형모델에서 대부분 제작합니다. 그러므로 이 시간 이후부터는 메모리모델을 대형모델로 설정해놓고 프로그램을 만드는 것이 좋습니다.
**요약: 대형 모델은 함수 포인터와 데이터 포인터가 모두 원거리 포인터를 사용합니다. 크기가 64KByte 이상인 exe 파일은 대부분 대형모델에서 만듭니다.
32.1.6. 거대 모델(huge model)
대형모델과 거의 다 같으나 정적데이터 영역을 64KByte 이상 가질 수 있다는 점이 다릅니다. 덩치가 큰 특수한 자료 파일을 실행파일 안에 저장하고 싶을 때 사용하며 평상시에는 거의 사용하지 않습니다. 특수한 자료파일이란 글꼴파일이나 그림파일 등을 말합니다.
32.2. 주소 또는 번지
주소란 각종 자료가 위치할 컴퓨터 내의 위치를 말합니다.
프로그램을 짜는 사람이 가장 골머리를 앓는 부분이 주소와 관련된 내용입니다. 앞서 변수를 미리 선언해두면 자리를 마련해둔다고 했습니다. 이때 마련하는 자리는 나름대로의 위치가 정해져 있을 겁니다. 주소의 개념을 넓게 생각하면 무슨 동 몇 번지라고 표현할 수 있고, 좁게 생각하면 한 건물 안에서 몇 층 몇 호라고 표현할 수 있습니다. 대부분의 작업공간은 주소를 가지고 있습니다. 집도 공장도 사무실도 모두 주소를 가지고 있습니다. 그런데 하나의 주소에 아무런 관계가 없는 두 사람을 집어넣으면 어떻게 되겠습니까? 큰 문제가 발생할 겁니다. 비행기표를 끊고 탔는데, 같은 좌석번호에 두 명이 배정되었다거나 호텔 방에 들어갔더니 다른 사람들이 자기가 예약한 방이라고 우기면 난리가 납니다. 집을 하나 샀는데 이중 등기가 되었다 해도 문제입니다. 통상 하나의 주소에는 한 명의 소유자를 인정하기 마련입니다.
마찬가지로 컴퓨터 안에도 각종 주소가 있고 각 주소를 점유할 수 있는 소유자도 한 명이어야 합니다. 컴퓨터의 주기판에 장착된 부품이 나름대로 고유한 주소를 가지고 있습니다. 그러나 프로그램을 짤 때 가장 중요한 주소는 역시 램의 주소입니다. 램을 하나의 작업공간인 사무빌딩이나 공장으로 생각해봅시다.
주인인 내가 하드디스크에 든 파일목록을 정리해서 프린터로 출력하라고 명령을 내렸습니다. 그런데 컴퓨터가 파일목록을 정리한 자료는 일단 3층 10호 방에 넣어두고, 복사할 때는 2층 4호 방에 있는 자료를 가져다가 프린터로 출력했다고 합시다. 이러면 작업내용이 엉망이 되는 셈입니다. 그러므로 파일목록을 정리한 자료를 3층 10호 방에 보관해두라고 했으면, 나중에 그 자료를 가져올 때도 3층 10호 방에 가서 가져와야 합니다. 엉뚱한 방을 찾아들어가면 골치 아픈 문제가 생깁니다.
컴퓨터에서 다루는 주소는 인간 세계의 주소와 같은 개념입니다.
컴퓨터를 다루거나 프로그램을 짜는 사람이 가장 골치 아프게 생각하는 것이 바로 주소와 관련한 내용입니다. 몇 층 몇 호실에 무슨 자료를 넣어두었는지 일일이 파악을 하고 있어야 하기 때문입니다. 문제는 이들 주소가 사람들이 알기 쉽도록 표기되지 않고 복잡한 이진수나 16진수로 표시된다는 점입니다. 그러다보니 1333번지에 있는 자료를 가져와서 더하라고 명령을 내려야 하는데 1332번지 자료를 가져와서 더하라고 명령을 내리기 일쑤입니다.
우편물을 정확하게 배달하는 것이 쉬운 일이 아닌 것처럼 원하는 주소에 원하는 자료를 배달하고 다시 가져오는 일도 쉬운 일이 아닙니다. 우편물에 우편번호와 주소를 정확하게 써야 하는 것처럼 컴퓨터에서도 정확한 주소를 적어주고 명령을 내려야 자료의 유실을 막을 수 있습니다. 하여간 컴퓨터에서 말하는 주소는 일반적인 사회에서 말하는 주소와 같은 개념이라는 점을 알아두시기 바랍니다.
**요약: 컴퓨터가 자료를 저장할 때는 일정한 규칙에 의해서 정한 주소(또는 번지)를 사용합니다. 즉 주소란 컴퓨터가 자료를 저장해둔 위치를 가리키는 말입니다. 한 주소에는 하나의 자료만 저장할 수 있습니다.
32.3. 선입선출과 후입선출의 차이
선입선출(FIFO=First In First Out)은 먼저 들어간 놈이 먼저 나온다는 뜻입니다. 즉 먼저 집어넣은 자료가 먼저 나온다는 이야기입니다. 선입선출의 개념을 비교하면 입구와 출구가 있고 한 사람이 통과할 수 있는 긴 복도를 통과하는 일과 같습니다. 즉 입구 쪽에서 사람이 들어가면 먼저 들어간 사람이 출구 쪽으로 나오게 될 겁니다. 그러므로 선입선출은 보통 두 개의 문이 존재합니다. 들어가는 문과 나가는 문이 따로 있는 겁니다. 양쪽에 구멍이 있는 호스가 있을 때 한 쪽에서 구슬을 넣으면 먼저 들어간 구슬이 다른 구멍으로 나오는 먼저 나오는 것과 같습니다.
후입선출(LIFO=Last In First Out)은 이와 반대로 먼저 들어간 자료가 가장 늦게 나오는 것을 말합니다. 이는 출구가 따로 없는 좁은 복도에 사람을 집어넣는 일로 비유할 수 있습니다. 즉 들어간 문이 나가는 문이 될 경우에는 먼저 들어간 사람보다는 맨 마지막에 들어간 사람이 나올 때 먼저 나오게 됩니다. 호스 한 쪽을 막고 구슬을 넣은 다음에 다시 구슬을 빼면 가장 늦게 들어간 구슬이 먼저 나오는 것과 같습니다.
선입선출과 선입후출은 주로 메모리를 다룰 때 자주 접하게 되는 개념입니다. 예를 들어서 우리가 배운 자동변수는 스택이라는 기억장소에 저장되는데 이때 스택은 후입선출방식으로 메모리를 관리하는 곳입니다. 그래서 자료를 집어넣을 때는 밀어넣기로 집어넣고, 나올 때는 밀어넣은 순서와 반대로 튀어나옵니다. 택시를 타면 택시기사들이 사용하는 동전보관통을 생각하면 후입선출의 예를 쉽게 알 수 있습니다.
[보기] 후입선출의 보기
- 비어있을 때
T
- 10을 넣음
10
T
- 20을 넣음
20
10
T
- 30을 넣음
30
20
10
T
- 30부터 뺌
20
10
T
- 다음에 20을 뺌
10
T
반면 선입선출은 힙이라는 메모리에서 주로 사용하는 방식으로 힙에는 배열과 초기화된 전역 변수 등이 저장됩니다.
[그림] 선입선출의 보기
- 비어있을 때
입구| | | |출구
- 10을 넣음
입구|10| | |출구
- 20을 넣음
입구|20|10| |출구
- 30을 넣음
입구|30|20|10|출구
- 40을 넣음
입구|40|30|20|출구=) 10 (출구로 10이 나옴)
그림을 통해서 두 방식의 차이를 알 수 있으리라 생각합니다. 이 책에서는 두 방식이 어떤 차이를 가지고 있는지 정도만 이해하시면 될 것으로 생각합니다.
32.4. 코드, 데이터, 스택, 힙, 큐, 데크의 의미와 차이
언어 책을 보면 스택이나 힙, 큐, 데크라는 말이 나옵니다. 물론 이 말의 뜻을 몰라도 프로그램 짜는데 어려움은 없습니다. 모든 것은 컴파일러라 알아서 해주니까요. 그렇지만 용어의 의미도 모르고 프로그램을 만들려면 조금 답답합니다.
이들 용어는 사용하는 곳에 따라서 의미가 조금 다릅니다. 자료 구조에서 사용할 때와 메모리에서 사용할 때 의미가 조금씩 다릅니다. 자료 구조론에서는 스택과 큐, 데크 등의 용어를 사용합니다. 반면 프로그램을 만들 때는 스택과 힙이라는 용어를 많이 사용합니다.
먼저 우리가 보통 스택과 큐, 힙을 말할 때는 C나 C++의 메모리 구조와 관련된 용어로 사용 합니다. C/C++에서 메모리는 다음과 같은 계층을 이룹니다.
1. 코드(code) 영역
2. 데이터(data) 영역
3. 힙(heap) 영역
4. 스택(stack) 영역
코드 영역은 코드 자체를 구성하는 메모리 영역입니다. 즉 프로그램 명령이 위치하는 곳으로 기계어로 제어되는 메모리 영역입니다. 하위 메모리라고 부르는 가장 낮은 쪽에 있는 메모리 영역입니다. 이 부분은 기계어 부분이므로 프로그래머가 신경 쓸 이유가 없습니다.
데이터 영역에는 데이터가 보관됩니다. 예를 들면 전역(global) 변수, 정적(static) 변수, 그외 초기화된 각종 배열과 구조, 자료들이 저장됩니다.
힙 영역은 프로그래머가 스스로 할당한 메모리 영역을 뜻합니다. 즉 터보C의 함수 중에 메모리를 할당하는 함수인 malloc() 등을 사용하여 배정한 메모리가 힙 영역에 해당합니다. 메모리 모델에 따라서 사용하는 함수가 달라지는데 메모리 할당 때는 malloc() farmalloc() 함수를 사용하고 재배정 때는 realloc() 함수를, 메모리 해제 때는 free()나 farfree() 함수를 사용합니다.
스택 영역은 프로그램이 자동으로 사용하는 임시 메모리 영역에 해당합니다. 즉 자동 변수를 저장하거나 함수로 인수를 보낼 때, 복귀 번지를 저장할 때 등에 사용합니다.
스택과 힙은 사용 용도에 따라서 조금씩 다른 의미로 사용합니다. 예컨대 버퍼 메모리에서 스택고 힙이라는 용어를 사용하면 버퍼 메모리를 구성하는 두 가지 방식을 뜻합니다. 이때 스택은 후입선출(LIFO=Last In First Out) 방식의 버퍼를 말하고, 힙은 선입선출(FIFO=First In First Out) 방식의 버퍼를 뜻합니다.
스택의 경우 후입선출 방식이므로 동작 과정이 푸시(push)와 팝(pop)의 과정으로 이루어집니다. 이를 통해 동작이 한 쪽 끝(top)에서만 일어납니다. 다시 말해서 자료가 들어가는 구멍(입구)과 나오는 구멍(출구)이 하나입니다. 이 때문에 맨 마지막에 들어간 것이 제일 먼저 나오는 겁니다.
큐(Queue)는 프로그램 언어에서 보면 자료 구조의 한 형태로 순차 목록의 한 형태를 뜻합니다. 원소의 삽입은 뒤(rear)에서 이루어지고 삭제는 앞(front)에서 이루어지는 자료 구조를 뜻합니다. 메모리에 적용할 경우 큐는 선입선출 방식을 뜻합니다. 이 때문에 힙과 큐를 혼동해서 사용하기도 합니다. 의미는 같지만 큐는 자료 구조론에서 사용하는 용어고, 힙은 메모리 관련 용어로 사용한다고 보면 됩니다.
데크(Deque)는 Double Ended QUEue의 줄임말로 스택과 큐의 동작 방식을 복합한 방식입니다. 자료 구조에서 선형구조의 목록을 뜻하는 용어로 목록의 양 쪽 끝에서 삽입과 삭제가 가능한 방식입니다.
데크는 입출입 형태에 따라서 한 쪽을 제한할 수 있습니다. 입력 제한 데크라는 방식은 scroll이라고 하는데, 삽입(input)은 목록의 한 쪽 끝에서 이루어지고, 삭제(출력,output)는 목록의 양 쪽 끝에서 이루어지는 방식입니다. 반대로 출력 제한 데크가 있습니다. 출력 제한 데크는 shelf라고 하는데 삽입은 양 쪽 끝에서 이루어지고, 삭제는 목록의 한 쪽 끝에서 이루어지는 방식을 뜻합니다.
출처 : http://www.dal.kr/chair/c/c3201.html