단축평가는, 계산을 하는 도중에 이미 결과값이 확정된 경우에, 나머지 계산 과정을 생략하는 것입니다. 예를 들어서 A or B or C라는 수식이 있다고 해 봅시다. 만약에 A가 참이라면 어떨까요? B나 C가 참이던 거짓이던 A or B or C는 참이 될 겁니다. 즉, B나 C는 볼 필요가 없다는 겁니다. 예제를 통해서 이해해 봅시다.
먼저, a, b, c의 값은 각각 0, 0, 0입니다. 논리 연산자는 좌측에서 우측으로 들어가는데요. ((b++<7)||(c++<7))이 평가되기 전에, 먼저 (a++<10)이 평가가 됩니다. 조건절 (a++<10)을 A, 조건절 ((b++<7)||(c++<7))을 B라고 합시다. 그러면, if문은 A or B로 간단하게 할 수 있어요.
여기서 A의 값은 참인가요? 네. a++의 값은 0이기 때문에, 조건절 (a++<10), 즉 A는 참이 됩니다. 이미 결과값이 확정이 되었기 때문에, 조건절 B를 검사하지 않습니다.
따라서 a만 1 증가한 결과가 나오겠네요.
그러면 이 프로그램은 어떨까요? ((b++<7)||(c++<7))을 조건절 B, (a++<10)을 조건절 A로 묶어봅시다. 그러면 A and B의 값을 구해야 합니다. 일단 조건 A는 참입니다. a는 10보다 작기 때문입니다. 그런데 A만 가지고 A and B의 값을 구할 수 있을까요? 아닙니다. T and T는 T이지만 T and F는 F이기 때문입니다. A만 봐서는 결과를 모릅니다. 따라서, 조건절 B도 평가를 하게 됩니다.
조건절 B는 (b++<7) or (c++<7)입니다. (b++<7)을 C, (c++<7)을 D라고 합시다. 그러면 이것은 C or D가 됩니다. b의 값은 0입니다. 0이 7보다 작다는 것은 참입니다. 조건절 B는 C or D였습니다. C가 참이기 때문에, D가 참이던 거짓이던 B는 참이 됩니다. 따라서, (c++<7)은 수행되지 않습니다.
(a++<7)이 실행되고, (b++<7)이 실행이 되었기 때문에 a, b, c의 값은 각각 1, 1, 0이 나옵니다.
다음 예제 프로그램을 봅시다.
이 프로그램은 어떻게 동작할까요? 일단 if에 걸려있는 조건절은 2개입니다. (a++>=0)인가? (b++>=0)인가? 이 중에서, 앞의 것을 먼저 봅니다. 그런데 보니까 a의 값이 -10인데, 이 값은 0보다 크거나 같지 않습니다. if에 걸려있는 조건은 A and B로 단순화 시킬 수 있는데요. 이 중 A가 거짓이였습니다.
A가 거짓이기 때문에, B가 참이던 거짓이던 A and B의 값은 거짓입니다. 따라서, (a++>=0)만 평가되고, (b++>=0)은 평가가 되지 않습니다.
따라서, 실행 결과는 -9와 0이 나옵니다. 그러면 두 조건절의 순서를 바꾸면 어떨까요?
그러면 먼저 (b++>=0) 조건절이 먼저 수행됩니다. 0은 0보다 크거나 같으므로 참입니다. A and B에서 A값이 참입니다. 그러면, A and B가 참인지 거짓인지 검사하기 위해서, B를 검사해야 할까요? 말아야 할까요? 당연하게도 검사해야 할 겁니다. 왜냐하면, B가 거짓이라면 A and B는 거짓이 될 거고, B가 참이라면 A and B가 참이 될 것이기 때문입니다.
(b++>=0)이 참이였기 때문에, (a++>=0)도 평가를 합니다. 여기서 (a++>=0)은 거짓이였기 때문에, A and B는 거짓입니다. 그런데, 이전 프로그램하고 차이는, 1개 조건절만 검사하고 끝내버렸느냐, 아니면 2개 조건절을 다 검사했느냐는 겁니다. A and B는 A가 거짓이면 B가 참이던 거짓이던 거짓이기 때문에, 평가를 끝내요. 단축 평가를 한 셈입니다. 그런데, 위 예제 프로그램은 안 그렇습니다. (b++>=0)이 참이였지만, (a++>=0)이 참이냐 거짓이냐에 따라서, if문에 걸려있는 조건이 참인지 거짓인지가 결정되기 때문에, (a++>=0) 또한 평가를 할 수 밖에 없습니다.
따라서 a는 -9, b는 1이 되겠네요.
이제 조금 어려운 예제를 봅시다. 흔히 우리가 bfs를 짤 때, 경계 검사를 먼저 하고, 방문했는지를 검사합니다. 그러면, 아래 코드는 어떤 점이 문제일까요? 단순히 검사 순서를 바꾼 것이 문제가 되었을까요?
사실, bfs를 재귀호출 한 것 때문에 문제가 되지 않습니다. visit[a] == 0를 평가하고, a<=n을 평가한다는 것이 문제인데요. visit[a] == 0을 평가하기 위해서 visit[a]에 접근해야 합니다.
그 경우, a가 경계를 넘어가더라도 visit[a]에 접근하기 때문에 런타임 에러가 뜰 수도 있습니다. 하지만, 순서를 바꾸면 이야기가 달라집니다. 경계 조건인, a<=n이 거짓이라면, (visit[a] == 0)이 평가가 되지 않기 때문에, 제대로 동작합니다. 내용이 다소 길어졌는데요. 기억할 것은 딱 1가지입니다. 왼쪽 조건 절부터 평가된다. 만약에 중간에 결과값이 확정이 되었다면, 나머지 조건절은 평가되지 않는다. 예를 들어 A and B and C and D라는 조건이 있을 때, A가 거짓이라면, B, C, D는 평가되지 않는다. 정도만 짚고 넘어가시면 좋겠습니다.
'코딩 > C' 카테고리의 다른 글
c언어 double형 vs float형 : 어떤 차이가 있을까요? (2) | 2019.08.06 |
---|---|
1의 보수 vs 2의 보수 : 음수는 어떻게 표현되는가? (2) | 2019.07.28 |
부동 소수점 : 왜 0.1을 저장하면 오차가 생길까요? (0) | 2019.06.29 |
c언어 비트 이동 연산자 (<<, >>) : 어떤 것을 조심해야 할까요? (0) | 2019.06.26 |
c언어 비트 연산자 : ps를 하려면 알고 넘어갑시다. (0) | 2019.06.25 |
최근댓글