Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ volatile 키워드란 무엇이고 언제 사용해야 할까?

C++에서 volatile 한정자(qualifier)는 변수를 선언할 때 함께 지정하는 키워드로, 컴파일러에게 "이 변수의 값은 언제든지 외부 요인에 의해 변경될 수 있다"고 알려주는 역할을 합니다. 이를 통해 컴파일러는 해당 변수에 대한 과도한 최적화를 수행하지 않게 됩니다.

volatile의 주요 특징

  • volatile 키워드가 붙은 변수는 메모리 할당이 제거되지 않습니다.
  • 변수 값이 CPU 레지스터에 캐싱되지 않으며, 항상 메모리에서 직접 읽고 씁니다.
  • 값은 할당된 순서 그대로 변경되며, 컴파일러가 임의로 재배치하지 않습니다.

volatile 선언 방법

volatile int a;
int volatile a;

위 두 가지 선언 모두 올바른 표현입니다. 다른 자료형과 마찬가지로 volatile 포인터, 구조체(struct), 공용체(union) 등에도 사용할 수 있습니다. volatile로 선언된 구조체나 공용체는 그 자체가 volatile이 되며, 내부 멤버 변수 역시 volatile 타입으로 취급됩니다.

volatile이 필요한 대표적인 상황

volatile은 다음과 같은 경우에 주로 활용됩니다.

  • 메모리 맵드(Memory-mapped) 방식으로 접근하는 주변 장치 레지스터
  • 인터럽트 서비스 루틴(ISR)이나 다른 함수에 의해 값이 변경될 수 있는 전역 변수
  • 멀티스레드 애플리케이션에서 여러 스레드가 공유하는 변수

이런 환경에서는 프로그램 코드 외부의 요인이 변수 값을 바꿀 수 있기 때문에, 컴파일러가 변수를 레지스터에 고정해 버리면 최신 값을 읽지 못하는 문제가 발생합니다. volatile은 바로 이러한 문제를 방지합니다.

예제 코드 비교

// volatile 미사용
int main() {
    int value;
    value++;
}

// volatile 사용
int main() {
    volatile int value;
    value++;
}

두 코드 블록을 비교해 보겠습니다. 첫 번째 코드에는 volatile이 없으므로, 컴파일러는 최적화 과정에서 변수 값을 메모리에서 CPU 레지스터로 복사한 뒤 연산을 수행합니다. 반면 두 번째 코드에는 volatile이 선언되어 있기 때문에, 컴파일러는 해당 변수를 레지스터로 옮기지 않고 항상 메모리에서 직접 값을 읽고 씁니다.

덕분에 하드웨어나 인터럽트 같은 외부 요인에 의한 값 변화를 프로그램이 정확하게 감지할 수 있으며, 이것이 volatile 키워드의 핵심적인 존재 이유입니다.