Skip to content

Commit 31d7b8c

Browse files
committed
✏ 부족한 설명 보완
1 parent 137b529 commit 31d7b8c

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

8-functions/README.md

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,32 @@
66

77
지금까지는 컴퓨터가 단순히 메모리와 연산장치가 있다고만 생각했었는데요, 사실 연산장치에도 계산하고 있는 값을 임시로 저장하기 위한 메모리가 하나 더 있습니다. 지금까지 우리가 다룬 주소값이 있는 메모리는 흔히 램이라고 부르는 `임의 접근 메모리(Random-access memory; RAM)`이고, 연산장치에 있는 계산 중인 값을 저장하기 위한 메모리는 `레지스터(register)`입니다.
88

9+
덧셈, 뺄셈 같은 산술 연산이든, 논리곱, 논리합 같은 논리 연산이든, 연산장치가 값을 계산하기 위해선 피연산자들이 반드시 레지스터에 들어있어야 합니다. 연산장치가 RAM 안의 공간에 대해서 할 수 있는 연산은 불러오기와 저장하기 밖에 없습니다. 다음 예시를 봐주세요.
10+
11+
```c
12+
int main()
13+
{
14+
int a = 2, b = 5;
15+
int c = a + b;
16+
}
17+
```
18+
이런 코드를 지금까지는
19+
```
20+
프로그램이 시작했을 때,
21+
1. 적절한 공간을 a와 b라고 이름짓고 2와 5을 집어넣습니다.
22+
2. 적절한 공간을 c라고 이름짓고 a와 b에 들어있는 값의 합을 집어넣습니다.
23+
```
24+
이렇게 분석했지만, 실제 컴파일 결과는
25+
```
26+
프로그램이 시작했을 때,
27+
1. 적절한 공간을 a와 b라고 이름짓고 2와 5을 집어넣습니다.
28+
2. 레지스터 ecx에 b의 값을 불러옵니다.
29+
3. 레지스터 eax에 a의 값을 불러옵니다.
30+
4. eax에 ecx와 eax에 들어있는 값의 합을 집어넣습니다.
31+
5. 적절한 공간을 c라고 이름짓고 eax에 들어있는 값을 집어넣습니다.
32+
```
33+
이렇게 된다는 것입니다.
34+
935
연산장치 입장에서 레지스터는 RAM보다 가까운 곳에 있기 때문에 더 쉽고 빠르게 접근할 수 있습니다. 그래서 자주 변하는 값은 레지스터에 저장하는 것이 좋습니다. 프로그래머가 C 코드를 통해 변수를 생성하게 되면, 컴파일러는 자체적인 판단에 따라 그 변수를 RAM 또는 레지스터에 고정시킵니다. 그 변수에 주소 연산자를 사용한 경우가 있으면 RAM에 고정시켜야겠지만, 그런 경우가 없으면 레지스터에 고정시켜도 괜찮을 것입니다.
1036

1137
레지스터들은 계산 중인 값을 저장하는 것 말고도 여러가지 목적을 위해 사용됩니다. 그래서 연산장치를 만드는 회사들은 레지스터들을 목적에 맞게 분류하고, 그 분류에 따라 연산장치의 알맞은 곳에 레지스터를 배치해놓습니다. 컴파일러를 만드는 회사들은 이런 분류에 맞추어 변수가 알맞은 레지스터에 고정되도록 합니다.
@@ -24,16 +50,17 @@ int main()
2450
}
2551
```
2652

27-
여기서 `i` 같은 변수를 `루프 카운터(loop counter)`라고 부르는데요, 레지스터에 고정되는 예시 중 하나입니다. `i``ebx`라는 레지스터에 고정되고, `d`가 800\~804를 차지한다고 가정했을 때, 위 코드를 해석해보면,
53+
여기서 `i` 같은 변수를 `루프 카운터(loop counter)`라고 부르는데요, 레지스터에 고정되는 예시 중 하나입니다. `d`가 800\~804를 차지한다고 가정했을 때, 위 코드를 해석해보면,
2854

2955
```
3056
1. 800번을 d라고 이름짓습니다.
3157
2. 사용자의 입력을 받아 d가 차지하고 있는 공간에 정수를 넣습니다.
32-
3. ebx에 0을 집어넣습니다.
33-
4. ebx가 d에 들어있는 값보다 작으면 5로 이동하고, 아니면 for문을 종료합니다.
34-
5. ebx에 들어있는 값을 출력합니다.
35-
6. ebx에 들어있는 값을 1 증가시킵니다.
36-
7. 4로 이동합니다.
58+
3. 레지스터 ebx에 0을 집어넣습니다.
59+
4. 레지스터 ecx에 d의 값을 집어넣습니다.
60+
5. ebx < ecx의 결과가 1이면 6로 이동하고, 아니면 for문을 종료합니다.
61+
6. ebx에 들어있는 값을 출력합니다.
62+
7. ebx에 들어있는 값을 1 증가시킵니다.
63+
8. 5로 이동합니다.
3764
```
3865

3966
이렇게 해석될 수 있습니다.
@@ -131,7 +158,7 @@ goto <레이블 이름>;
131158

132159
선언문을 제외한 임의의 문장에 레이블로 이름을 달 수 있는 것을 알 수 있습니다.
133160

134-
> 사실 `선언문(declaration)``문장(statement)` 아니지만, 선언문을 문장으로 보면 이해하기 더 쉬운 경우가 있기 때문에(`int main { ... }`안에는 항상 문장만 들어간다고 생각할 수 있는 등) 둘을 혼용해서 설명했었습니다. 이 경우는 선언문과 문장이 서로 다르게 취급되는 몇 안되는 경우입니다. 앞으로 설명의 편의를 위해 **선언****선언문**이라는 용어를 혼용하겠습니다. 둘 다 declaration을 번역한 용어라고 생각해주세요.
161+
> 사실 `선언문(declaration)``문장(statement)` 아니지만, 선언문을 문장으로 보면 이해하기 더 쉬운 경우가 있기 때문에(`int main { ... }`안에는 항상 문장만 들어간다고 생각할 수 있는 등) 둘을 혼용해서 설명했었습니다. 이 경우는 선언문과 문장이 서로 다르게 취급되는 몇 안되는 경우입니다. 앞으로 설명의 편의를 위해 **선언****선언문**이라는 용어를 혼용하겠습니다. 둘 다 declaration을 번역한 용어라고 생각해주세요.
135162
136163
예제를 보겠습니다.
137164

@@ -212,7 +239,7 @@ end:;
212239

213240
`end:` 다음에 세미콜론이 있는 것에 주목해주세요. 레이블 다음엔 반드시 문장이 와야하기 때문에, `end:` 다음에 아무것도 안 한다면 빈 문장으로 세미콜론 하나를 적어야 합니다.
214241

215-
goto문은 너무 많이 사용하면 코드가 읽기 힘들어지기 때문에, goto문을 사용해야하는가에 대한 논쟁이 많이 있었습니다. [이건](https://stackoverflow.com/questions/46586/goto-still-considered-harmful) StackOverflow의 한 질문인데, 무려 49개의 답변이 달린 것을 알 수 있습니다. goto가 정확히 어떤 일이 일으키는지 알고 쓰면 괜찮을 수 있지만, 실수를 일으키기 좋고 대부분의 경우 대체할 수 있는 방법이 있다라는 의견이 많이 보입니다. 즉, "위험성은 큰데 얻을 수 있는 건 적다"는 겁니다. 특히 이중에는 "goto문이 유일한 해법인 것처럼 보이는 경우는 사실 다른 부분의 디자인도 별로인 경우"라고 주장하는 사람도 있었습니다. 그래서 goto문은 되도록 사용을 지양하는 것이 좋을 것 같습니다.
242+
goto문은 너무 많이 사용하면 코드가 읽기 힘들어지기 때문에, goto문을 사용해야하는가에 대한 논쟁이 많이 있었습니다. [이건](https://stackoverflow.com/questions/46586/goto-still-considered-harmful) StackOverflow의 한 질문인데, 무려 49개의 답변이 달린 것을 알 수 있습니다. "goto가 정확히 어떤 일을 일으키는지 알고 쓰면 괜찮을 수 있지만, 실수를 일으키기 좋고 대부분의 경우 대체할 수 있는 방법이 있다"라는 의견이 많이 보입니다. 즉, "위험성은 큰데 얻을 수 있는 건 적다"는 겁니다. 특히 이중에는 "goto문이 유일한 해법인 것처럼 보이는 경우는 사실 다른 부분의 디자인도 별로인 경우"라고 주장하는 사람도 있었습니다. 그래서 goto문은 되도록 사용을 지양하는 것이 좋을 것 같습니다.
216243

217244
물론 goto가 좋다고 생각되는 경우도 몇몇 있습니다. 반복문 안에 반복문을 쓴 경우가 그 예입니다. 3행 3열의 표에 숫자를 저장하되, 대각선 위에 있는 칸에는 음수를 저장하지 않는 프로그램을 만들고 싶습니다. 대각선 위에 있는 칸에 음수를 입력하면 프로그램을 강제종료하고자 합니다.
218245

@@ -275,6 +302,6 @@ int main()
275302
}
276303
```
277304

278-
이렇게 복잡하게 적어야합니다. `if (!valid) break;`가 없으면 `2 2`에서 음수를 입력했어도 `3 1`이동했을 것입니다.
305+
이렇게 복잡하게 적어야합니다. `if (!valid) break;`가 없으면 `2 2`에서 음수를 입력했어도 `3 1`이동합니다.
279306

280307
> C++에선 RAII라는 것 때문에, goto를 쓰고 싶어도 쓰면 컴파일 오류가 발생하는 경우가 많습니다. RAII에 대해선 나중에 다루도록 하겠습니다.

0 commit comments

Comments
 (0)