volatile 변수
오늘은 C언어의 volatile 변수에 대해 알아 보려고 한다.
volatile은 변수를 선언할 때 변수 앞에 붙일 수 있는데, 이 키워드는 해당 변수를 최적화에서 제외하는 역할을 한다.
이게 무슨 말인지 알려면 C언어의 컴파일러가 최적화하는 방식에 대해서 알아야한다.
예를 들어서, 다음과 같은 코드가 있다고 가정한다.
int i = 0;
while(i < 10) {
i ++;
}
C언어의 컴파일러는 이 코드를 최적화 하기 위해 while문을 없애버리고 그냥 i에 10을 할당하는 최적화 방식을 가지고 있다.
반복되는 구문과 같은 불필요한 연산을 최적화한다고 생각하면 된다.
일반적인 상황에서는 이러한 최적화가 큰 이득이 될 것이다.
하지만 만약 저 구문이 하드웨어 레지스터에 값을 쓰는 프로그램이라던가, 필수적으로 실행했어야 하는 구문이었다면 원하는 결과가 나오지 않을 것이다.
이를 방지하기 위해서 사용되는 변수가 바로 volatile 변수이다.
volatile int i = 0;
while(i < 10) {
i ++;
}
이와 같이 변수를 선언하면 컴파일러는 while문을 없애지 않고 제대로 돌려서 i에 10이라는 값을 할당하게 된다.
사용 예시
필자는 이 키워드를 아두이노에서 사용하게 되었다.
내용을 복기해보며 더 자세히 설명해보자면 아래와 같다.
extern volatile unsigned long timer0_millis;
위에서 timer0_millis
변수는 아두이노의 실행 시간을 계산하는 함수인 millis()의 내부 변수로 쓰인다.
이를 전역적으로 가져오기 위한 extern
와 변수가 바뀔 수 있음을 알려주어 최적화에서 제외하는 volatile
을 사용했다.
volatile
을 통해 timer0_millis
변수는 항상 메모리에서 최신 값을 읽어오게 되고, 최적화로 인해 발생 할 수 있는 컴파일러가 해당 변수를 변경되지 않는 값으로 가정하는 문제를 해결할 수 있다.
정리
volatile
은 컴파일러에게 최적화 대상에서 제외하도록 하는 키워드로써 사용된다.- 컴파일러에게 최적화 대상은 아래와 같다.
- 불필요한 연산을 수행하는 경우 (ex_ 반복되는 연산)
- 변경되지 않을 값이라고 가정할 수 있는 경우
- 위와 같은 상황에 컴파일러는 이미 계산된 값 혹은 이전에 읽어온 값을 레지스터에 저장함으로써 최적화를 진행하게 된다.
volatile
은 위와 같이 컴파일러가 최적화하는 상황을 방지하기 위해 사용되며, 사용 예시에서 언급된 것 처럼 항상 변경될 수 있는 값임을 명시하여 메모리에서 값을 읽어오도록 한다.- 이는 주로 시스템이 직접 값을 변경하는 변수에 대해 사용되거나, 하드웨어에서 항상 최신 값을 가져와야 할 때 쓰인다.
- 보통 임베디드 시스템에서 자주 쓰이는 키워드이지만, 알아두는 것도 나쁘지 않을 것 같다.
이 글이 블로그 조회수 중 가장 많은 비중을 차지하고 있길래, 옛날 기억을 짜집기하여 리뉴얼 해보았다.
이 글을 읽는 분들이 더 많은 정보를 얻어갔으면 좋겠다.