while 문

while 문

조건이 참인 동안 같은 문장을 계속 실행하고 싶을 때가 많죠. C++의 while 문은 조건을 먼저 검사한 뒤, 그 조건이 참인 동안 statement를 반복해서 실행해요. 조건이 거짓이 되는 순간 루프가 끝나요.

출처: cppreference

본문

문법

attr (optional) while ( condition ) statement
자리 의미
attr (C++11부터) 임의 개수의 속성(attribute)
condition 조건
statement 문장 (보통 복합문)

조건(Condition)

조건은 표현식이거나 단순 선언(simple declaration)이에요.

  • 문법적으로 구조화 바인딩 선언(structured binding declaration)으로 해석될 수 있으면 그렇게 해석돼요. (C++26부터)
  • 문법적으로 표현식으로 해석될 수 있으면 표현식으로 취급해요. 그렇지 않으면 구조화 바인딩 선언이 아닌 선언으로 취급돼요. (C++26부터)

제어가 condition에 도달하면, 조건은 값을 산출하고 그 값으로 statement를 실행할지를 정해요.

표현식

condition이 표현식이면, 그것이 산출하는 값은 문맥상 bool로 변환된 값이에요. 그 변환이 잘못된 형태(ill-formed)면 프로그램도 잘못된 형태예요.

선언

condition이 단순 선언이면, 그것이 산출하는 값은 판단 변수(decision variable, 아래 참고)의 값을 문맥상 bool로 변환한 값이에요. 그 변환이 잘못된 형태면 프로그램도 잘못된 형태예요.

구조화 바인딩이 아닌 선언

이 선언은 다음 제약을 가져요.

  • 문법적으로 다음 형태를 따라야 해요.
    • type-specifier-seq declarator = assignment-expression
    • attribute-specifier-seq(optional) decl-specifier-seq declarator brace-or-equal-initializer
  • 선언자는 함수나 배열을 지정할 수 없어요.
  • 타입 지정자 시퀀스(until C++11)는 타입 지정자와 constexpr만 포함할 수 있고, 클래스나 열거형을 정의할 수 없어요. (since C++11)

이 선언의 판단 변수는 선언된 변수예요.

구조화 바인딩 선언

이 선언은 다음 제약을 가져요.

  • 초기화식의 표현식은 배열 타입일 수 없어요.
  • 선언 지정자 시퀀스는 타입 지정자와 constexpr만 포함할 수 있어요.

이 선언의 판단 변수는 이 선언이 도입하는 발명 변수(invented variable) e예요. (C++26부터)

동작 방식(Explanation)

while 문은 다음 코드와 동등해요.

/* label */ :
if ( condition )
{
    statement
    goto /* label */ ;
}

condition이 선언이면, 그 선언이 선언하는 변수는 루프가 반복될 때마다 파괴되고 다시 생성돼요.

statement 안에서 루프를 끝내야 한다면 break 문을 종료 문장으로 쓸 수 있어요. 현재 반복만 끝내야 한다면 continue 문을 단축키로 쓸 수 있어요.

주의할 점(Notes)

statement가 복합문이 아니어도 항상 블록 스코프(block scope)를 도입해요. 그 안에 선언된 변수는 루프 본문 안에서만 보여요. 즉,

while (--x >= 0)
    int i;
// i는 스코프를 벗어남

이는 다음 코드와 같아요.

while (--x >= 0)
{
    int i;
} // i는 스코프를 벗어남

C++의 전진 보장(forward progress guarantee)의 일부로, 관측 가능한 행동이 없는(observable behavior) 루프가 종료되지 않으면 동작이 정의되지 않아요(undefined behavior). (C++26부터 자명한 무한 루프는 예외) 컴파일러는 그런 루프를 제거할 수 있어요.

키워드

while

예제

여기서는 while 문의 세 가지 쓰임을 확인해 볼게요. 단일 문장 루프, 복합문 루프, 그리고 <cstring> 문자열 포인터를 선언 조건으로 써서 문자열을 한 글자씩 출력하는 루프까지요.

#include <iostream>

int main()
{
    // 단일 문장으로 된 while 루프
    int i = 0;
    while (i < 10)
         i++;
    std::cout << i << '\n';
    
    // 복합문으로 된 while 루프
    int j = 2;
    while (j < 9)
    {
        std::cout << j << ' ';
        j += 2;
    }
    std::cout << '\n';
    
    // 선언 조건을 사용한 while 루프
    char cstr[] = "Hello";
    int k = 0;
    while (char c = cstr[k++])
        std::cout << c;
    std::cout << '\n';
}

출력:

10
2 4 6 8
Hello

더 알아보기

  • do-while 문: 조건을 나중에 검사하는 반복문.
  • for 문: 초기화·조건·증감을 한 곳에 모은 반복문.
  • break / continue: 루프를 끝내거나 다음 반복으로 넘기는 제어문.