요약
C++의 식은 서로 다른 두 가지 일을 할 수 있다. 값을 내는 일과 프로그램의 상태를 바꾸는 일이다. x + 1 식은 값만 낸다. x = 7 식은 값을 내고, 그에 더해 x 변수를 바꾼다. x++ 식은 x 변수가 가졌던 값을 내고, x 변수에는 다른 값을 남긴다. 이 수업은 식의 값과 효과의 이 차이를 공부한다. 식으로서의 대입, 복합 대입, 전위형과 후위형의 증가와 감소, 그리고 식의 각 부분이 계산되는 순서이며, 이 순서는 표준이 일부만 정한다. 여기서 수업의 나머지를 이끄는 물음이 나온다. 표준은 프로그램에 대해 무엇을 약속하는가. 그 답은 정의된 동작에서 정의되지 않은 동작까지 네 등급으로 이루어진 목록으로, 지금까지 본 모든 경우를 모으고, 각 경우에 대해 무엇이 그것을 검출하는지(컴파일러, 새니타이저, 라이브러리), 그리고 무엇은 아무도 검출하지 못하는지를 말해 준다.
학습 목표
- 대입, 증가 연산, 호출에서 식의 값과 그 부수 효과를 구별한다.
- 값으로 쓰인
x++식과++x식의 결과를 예측하고, 복합 대입이 있는 프로그램을 손으로 따라간다. - 표준이 정한 순서 없이 한 변수를 두 번 수정하거나, 읽으면서 수정하는 식을 알아보고, 이를 별개의 문으로 다시 쓴다.
- 어떤 구문을 정의된 동작, 구현 정의, 미지정, 정의되지 않은 동작 가운데 하나로 분류하고, 각 부류마다 예를 하나씩 든다.
- 목록에 있는 정의되지 않은 동작 하나하나에 대해, 컴파일러가 경고하는지, 새니타이저나 라이브러리가 멈추는지, 아니면 아무것도 검출하지 못하는지를 말한다.
값과 효과
산술 연산 수업은 식을 하나의 값으로 환원되는 트리로 공부했다. 2 + 3 * 4 식의 값은 14이고, 그것을 계산해도 식 자체 바깥의 아무것도 바뀌지 않는다. 관계와 논리 수업은 값이 true 값이나 false 값인 조건에 대해 같은 일을 했다. 그러나 값을 내는 것 말고도 프로그램의 상태에 흔적을 남기는 식이 있다. 변수의 값을 바꾸거나, 화면에 쓰거나, 입력에서 읽는 식이다. 이 흔적을 부수 효과, 또는 간단히 효과라고 하며, “부수”라는 말이 덜 중요하다는 뜻은 아니다. x = 7 식에서는 효과, 곧 x 변수의 값이 7이 되는 것이 바로 우리가 노리는 바이다.
그렇다면 모든 식은 두 가지 물음을 가지고 읽어야 한다. 무엇을 내는가, 그리고 무엇을 하는가. 세 가지 예가 이 구별을 굳혀 준다. count + 1 식은 count 변수 바로 뒤의 수를 내고 아무 일도 하지 않는다. count 변수는 제 값을 유지한다. count = 9 식은 9를 내고 count 변수의 값을 9로 만든다. std::println("안녕") 호출도 식이며, 함수 호출이고, 그에게서 중요한 것은 효과, 곧 한 줄을 쓰는 일이다. 직접 만드는 함수는 함수 수업에서 공부하는데, 거기서 이 구별이 다시 나타난다. 결과를 계산하기만 하는 함수는, 그에 더해 바깥의 무언가를 바꾸는 함수보다 이해하기도 쉽고 테스트하기도 쉽다.
count + 1; 같은 문은 올바른 C++이다. 값이 계산된 뒤 버려지므로 아무 쓸모가 없고, GCC는 -Wunused-value 옵션으로 이를 경고한다. 식문은 그 효과 때문에 의미가 있다. 따라서 효과가 있는 식이야말로 프로그램을 움직이는 식이고, 또한 조심해야 하는 식이다. 효과는 어느 시점에 일어나는데, 그 시점이 언제나 읽는 사람이 짐작하는 시점은 아니기 때문이다.
콘텐츠를 불러오는 중…