C언어에서 전위 연산자 후위 연산자 조금 더 알아보기

낚시하는 곰·2025년 4월 11일

krafton jungle

목록 보기
51/52

1. 질문 내용

#사용자의 핵심 질문답변 핵심 요약
1전위는 ‘실행 전’에 1 증가, 후위는 ‘실행 후’에 1 증가.컴파일러는 그 ‘전/후’를 어떻게 구분하나?파서 단계에서 별도 문법 규칙(prefix vs postfix)을 인식 → AST에 PreIncExpr/PostIncExpr로 분리. 각 노드가 ‘증가 시점’과 ‘결과값’을 명시한다.
2AST 단계에서 보이는 tmp, val은 실제로 어디 저장되나?주로 레지스터(빈 슬롯 없으면 스택) 사용. tmp새로운 i 값, val표현식 결과를 담는다.
3전위(++i)에서 왜 val = tmp가 또 필요한가?전위 결과가 증가된 값이기 때문. valtmp가 같지만, 후위(i++)처럼 결과와 부작용을 분리하기 위한 일관성 유지.
4원래 변수 i에 언제 다시 저장(부작용)하나?전위: i 갱신 → 결과 사용.후위: 결과 사용 → i 갱신. 명령어 순서로 강제된다.
5어셈블리에서 그 흐름이 어떻게 보이나?전위 예: add eax,1mov [i],eaxmov [a],eax.후위 예: mov [b],eaxadd eax,1mov [i],eax.

2. 전위(++i)·후위(i++) 내부 동작 흐름

전위 (++i)

int a = ++i;
  • 1을 더한 값을 먼저 만든다.
  • 그 값을 i에 반영한다 (i = i + 1).
  • 그리고 그 증가된 값을 결과로 쓴다.

의사코드 흐름:

tmp  = i + 1      // 증가된 값 계산
i    = tmp        // i에 반영 (부작용)
val  = tmp        // 이 값이 최종 결과로 쓰임 (a에 저장)

후위 (i++)

int b = i++;
  • 먼저 i의 현재 값을 결과로 사용한다.
  • 그다음 i에 1을 더해서 다시 저장한다.

의사코드 흐름:

val  = i          // 아직 증가되지 않은 값 사용 (b에 저장)
tmp  = i + 1      // 증가된 값 계산
i    = tmp        // i에 반영 (부작용)

val은 표현식 결과용, tmp는 i 갱신용으로 역할이 다름


3. x86‑64 어셈블리 예시 (‑O0, GCC)

C 코드

int demo(int i) {
    int a = ++i;  // 전위
    int b = i++;  // 후위
    return a + b;
}

전위 구간

mov eax, [i]      ; eax = i
add eax, 1        ; eax = i+1  (tmp)
mov [i], eax      ; i = tmp     (부작용)
mov [a], eax      ; a = val     (증가된 값)

후위 구간

mov eax, [i]      ; eax = i      (val)
mov [b], eax      ; b = val      (증가 전)
add eax, 1        ; eax = i+1    (tmp)
mov [i], eax      ; i = tmp      (부작용)

차이점 : 전위는 add 직후 바로 i·a에 쓰고, 후위는 add 전에 결과를 백업.


4. ‘전/후’ 판단 로직 한눈에 보기

  1. 파싱 : ++id vs id++ → 서로 다른 AST 노드 생성
  2. IR : PreIncExpr / PostIncExpr 각각 고유한 평가 순서 보존

5. 실전 주의 사항

  • 중첩 사용 : i++ + i++ → 평가 순서 미정 ⇒ 정의되지 않은 동작(UB).

profile
취업 준비생 낚곰입니다!! 반갑습니다!!

0개의 댓글