증감 연산자

증감 연산자 (Increment/decrement operators)

증감 연산자는 변수의 값을 1만큼 늘리거나 줄이는 단항 연산자예요. a++처럼 뒤에 붙이는 후위(postfix) 형태와 ++a처럼 앞에 붙이는 전위(prefix) 형태가 있어요. 둘 다 값을 1 바꾸긴 하는데, "표현식의 값"이 다르게 반환돼요. 이 차이를 정확히 이해하는 게 반복문을 다룰 때 중요해요.

출처: cppreference Increment/decrement operators

본문

증감 연산자는 변수의 값을 1만큼 증가/감소시키는 단항 연산자예요.

후위(postfix) 형태가 있어요:

형태
expr ++
expr --

그리고 전위(prefix) 형태도 있어요:

형태
++ expr
-- expr

전위·후위 증감 연산의 피연산자 expr은 **수정 가능한 lvalue(modifiable lvalue)**여야 해요. 정수 타입(_Bool과 열거형 포함), 실수 부동소수점 타입, 또는 포인터 타입이어야 해요. cvr-한정, 비한정, atomic일 수 있어요.

후위 증감 연산자의 결과는 expr의 값이에요.

전위 증가 연산자의 결과는 expr의 값에 1을 더한 값이에요. 표현식 ++ee+=1과 같아요. 전위 감소 연산자의 결과는 expr의 값에서 1을 뺀 값이에요. 표현식 --ee-=1과 같아요.

증가 연산자는 피연산자에 적절한 타입의 값 1을 더하는 부작용을 시작해요. 감소 연산자는 피연산자에서 적절한 타입의 값 1을 빼는 부작용을 시작해요. 다른 부작용과 마찬가지로, 이 연산들은 다음 **시퀀스 포인트(sequence point)**에서나 그 이전에 완료돼요.

int a = 1;
int b = a++; // stores 1+a (which is 2) to a
             // returns the old value of a (which is 1)
             // After this line, b == 1 and a == 2

a = 1;
int c = ++a; // stores 1+a (which is 2) to a
             // returns 1+a (which is 2)
             // after this line, c == 2 and a == 2

어떤 atomic 변수에 대한 후증가/후감소는 메모리 순서 memory_order_seq_cst를 가진 원자 읽기-수정-쓰기 연산이에요. (C11부터)

포인터 산술의 한계와 피연산자에 적용되는 암시적 변환에 대해서는 산술 연산자 문서를 참고하세요.

참고 (Notes)

부작용이 수반되므로, 시퀀싱 규칙을 위반한 정의되지 않은 동작을 피하기 위해 증감 연산자는 주의해서 사용해야 해요.

증감 연산자는 복소수나 허수 타입에 대해 정의되지 않아요. 실수 1을 더하거나 빼는 일반적인 정의는 허수 타입에 효과가 없고, 허수에는 i를 더/빼고 복소수에는 1을 더/빼게 만들면 0+yiyi와 다르게 취급하게 되기 때문이에요.

C++(그리고 일부 C 구현)과 달리, 증감 표현식 자체는 결코 lvalue가 아니에요. &++a는 무효예요.

예제 (Example)

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int a = 1;
    int b = 1;

    printf("original values: a == %d, b == %d\n", a, b);
    printf("result of postfix operators: a++ == %d, b-- == %d\n", a++, b--);
    printf("after postfix operators applied: a == %d, b == %d\n", a, b);
    printf("\n");

    // Reset a and b.
    a = 1;
    b = 1;

    printf("original values: a == %d, b == %d\n", a, b);
    printf("result of prefix operators: ++a == %d, --b == %d\n", ++a, --b);
    printf("after prefix operators applied: a == %d, b == %d\n", a, b);
}

출력:

original values: a == 1, b == 1
result of postfix operators: a++ == 1, b-- == 1
after postfix operators applied: a == 2, b == 0
original values: a == 1, b == 1
result of prefix operators: ++a == 2, --b == 0
after prefix operators applied: a == 2, b == 0

더 알아보기

  • 포인터에 대한 증감의 한계와 암시적 변환은 산술 연산자 문서에서 이어져요.
  • 전위·후위 차이는 흔히 반복문(for/while)과 배열 인덱싱에서 크게 작용해요.
  • cppreference의 Increment/decrement operators 원문에서 표준 절 번호(C23/C17/C11/C99/C89)를 더 확인할 수 있어요.