2025. 3. 29. 16:36ㆍProgramming Language/C++
기본적인 내용은 모든 언어에서 비슷하기에 주의 해야할 점과 키워드를 보고 넘어가자.
주의점
이런 코드가 있다고 한다면 각 위치별로 결과를 예상했을때
이런 식으로 출력될것을 기대했다.
실행시켜보면
결과가 예상과 다르게 출력되는 부분이 있다.
왜 그럴까?
인터넷에 C++ shell로 검색해서
C++ Shell
cpp.sh
코드를 복사해온 다음에 여기 삽입해서 실행해보면
이 결과는 우리가 예상한 대로 된 것을 볼 수 있다.
근데 잘 보면
한 표현식 안에서 같은 변수를 순서없이 여러번 수정했다! 라고 경고를 표출시켜준다.
음..?
우리가 따로 순서를 지정해줘야하나..? 라고 생각이 든다.
근데 확인해보면
이 부분 처럼 하나의 변수에 대한 두가지 수정이 동시에 일어난다면 C++에서는 수행의 순서가 정의 되지 않는다.
이런 경우는 정의되지 않은 동작(undefined behavior)에 해당할 수 있다.
결과적으로 컴파일러는 어떤걸 먼저 수행해야 할지 보장하지 않기에 컴파일러에 따라 ++n1을 먼저하기도, n1++을 먼저 수행하기도 할 수 있다는 말이다.
그래서 항상 연산을 분리해서 명확하게 순서를 보장해주는 것이 좋다.
예를 들면
++n1;
int temp = n1 + n1++;
std::cout << temp << std::endl;
라던가
int a = ++n1;
int b = n1++;
std::cout << a + b << std::endl;
이런식으로
Sequence Point
sequence point란 앞의 연산이 반드시 끝나고 나서, 다음 연산이 시작되는 지점으로 변수의 값 변경이나 함수 호출 등의 효과가 확실히 일어난 후 다음으로 넘어가는 지점을 말한다.
이 squence point가 왜 필요할까?
만약 하나의 표현식 안에 같은 변수에 여러번 접근하거나 수정할 때 sequence point가 없다면 순서가 불명확하기에 정의되지 않은 동작(undefined behavior)이 발생할 수 있는데 sequence point가 있다면 순서가 보장되므로 안전하게 연산이 수행될 수 있다.
위에서 봤던 연산처럼
int i = 1;
int x = i++ + ++i; // undefined behavior (순서 보장 안 됨)
두가지 연산이 한번에 수행된다면 둘 중 어느 것이 먼저 실행될지 컴파일러가 보장하지 않는다.
그럼 sequence point가 추가되어 순서가 명확하다는건 어떤 상황을 이야기할까
int i = 1;
i++;
printf("%d\n", i); // 안전 — i가 증가한 뒤에 printf 호출됨
이렇게 되는 상황이다.
아니 그럼 sequence point는 구체적으로 뭘 말하는 걸까?
sequence point는
sequence point | 설명 |
; ( 세미 콜론 ) | 문장의 끝(하나의 문장이 끝나면 그 안의 연산은 모두 완료 된다) |
&&, ` | 논리 AND 연산자는 단락 평가(short-circuit evaluation)를 하기에 sequence point가 있는 것처럼 왼쪽 피연산자의 평가가 끝나야만 오른쪽을 평가하고 이렇게 왼쪽 → 오른쪽 평가에 대한 순서가 보장된다. |
함수 호출 | 함수 호출 전에 모든 인자가 계산 완료되어야 함 |
, 연산자 (콤마) | 앞의 연산이 끝나야 다음 연산 수행 |
을 말한다.
C++11 이후 표준에서는 "sequence point"라는 용어 대신
"sequenced before", "unsequenced", "indeterminately sequenced" 같은 개념으로 나누는데 이는 아래 표에 정리해뒀다.
종류 | 설명 | 예시 |
sequenced before | A가 B보다 반드시 먼저 실행됨 | a++; std::cout << a; |
unsequenced | A와 B 중 어느 쪽이 먼저 실행될지 모름 | a + ++a |
indeterminately sequenced | A와 B의 순서는 정해지지 않았지만, 동시에 실행되진 않음 | f1() + f2() |
이 내용은 조금 더 들어가면 깊이 볼 부분은 있지만 이것 또한 너무 깊어지면 진도가 안나가기에 일단 이런게 있다 정도만 이해하고 넘어가도록 하자.
결론은 같은 변수에 여러 번 접근(읽기/쓰기)하는 연산은 반드시 서로 sequence point로 분리해라 라는 것이다.
'Programming Language > C++' 카테고리의 다른 글
Ch 04. 연산자 - 03. 논리 연산자 (0) | 2025.03.29 |
---|---|
Ch 04. 연산자 - 02. 비교&관계 연산자 (0) | 2025.03.29 |
Ch 03. 입출력 - 03. cin (0) | 2025.03.29 |
Ch 03. 입출력 - 03. cout (0) | 2025.03.26 |
Ch 03. 입출력 - 02. scanf (0) | 2025.03.25 |