한국어
C/C++
 

volatile 타입 qualifier는 주어진 오브젝트가 컴파일러가 의도하지 않은 방식으로 변경될 수 있다는 것을 나타냅니다.

따라서, 컴파일러는 이 오브젝트를 최적화(optimization) 과정에서 제외시킵니다. 좀더 정확히 말해서, 이 오브젝트에 대한 참조(reference)나 변경(modification)은 se-quence point를 넘어다니며 최적화되지 않습니다. 단, sequence point 안에서 최적화될 수 있습니다.


일반적으로, volatile이 쓰이는 곳은 크게 세가지로 나누어 생각할 수 있습니다.

  • 첫째, (대부분 디바이스 드라이버라고 하는) 하드웨어를 직접 제어하는 코드
  • 둘째, setjmp와 longjmp 함수를 써서 non-local goto를 사용하는 코드
  • 셋째, 인터럽트 관련 signal handler에서 (보통 전역) 변수의 값을 설정할 때.


예를 들어, 어떤 시스템은 세 개의 특정 메모리 주소를 제공하고, 이 중 두개는 하드웨어의 정보를 알려 주는 데에 쓰이며, 나머지 하나는 하드웨어에 직접 데이터를 쓰기 위한 목적으로 사용한다고 가정해 봅시다. 읽는 목적으로 쓰는 주소는 각각 in1, in2라는 포인터가 가리키고 있고, 쓰기위한 주소는 out이라는 포인터에 저장되어 있다고 가정합시다. 이 경우 다음과 같은 코드를 예상할 수 있습니다:

 

volatile unsigned char *out;
volatile unsigned char *in1, *in2;
int i;
...

for (i = 0; i < N; ++i)
    *out = a[i] & (*in1 + *in2);

 

이 코드는 out이 가리키는 곳에, *in1과 *in2를 더해서, a[i]의 값과 AND한 결과를 쓰게 됩니다. (위 코드에서 volatile이 없다고 가정하면) 단순한 시스템일 경우, 루프를 매번 돌 때마다, *in1 + *in2를 수행해서, 그 결과를 a[i]와 더해, *out에 쓰게 되지만, 최적화를 수행한다면, 매번 *in1 + *in2 덧셈을 수행할 이유가 없습니다. 그래서 컴파일러는 보통 더한 결과를 특정 레지스터에 저장해 두고, 이 것을 루프를 반복할 때마다 a[i]와 더하는 코드를 만들어 냅니다. 그러나 *in1과 *in2는 하드웨어가 직접 건드리는 값이 들어 있으므로, 루프를 돌 때, 매번 같다는 보장을 할 수 없습니다. 따라서 최적화를 수행한 코드와 그렇지 않은 코드가 서로 실행 결과가 다르거나, 예상하지 못한 결과를 가져올 수 있습니다.

이 때, 관련된 변수인 in1, in2, out를 volatile로 선언함으로써, 이 변수들이 컴파일러의 의도와 상관없이 변경될 수 있다는 것을 알려주면, 컴파일러는 이 변수가 관계된 코드는 최적화 고려 대상에서 제외시킵니다. 또한 non-local goto 역할을 수행하는 함수 setjmp와 longjmp를 쓸 때, volatile을 유용하게 쓸 수 있습니다.

 

번호 제목 글쓴이 날짜 조회 수
공지 C Programming FAQs(한글번역 pdf문서) makersweb 2014.03.18 27685
22 C코드 최적화 pjk 2014.02.10 5886
21 C언어 강좌-배열과 포인터 file makersweb 2014.03.10 5166
20 영어를 C언어로, 또는 C언어를 영어로 변환 해주는 cdecl makersweb 2014.03.19 8564
19 예제소스를 통해 리틀엔디안(Little endian)과 빅엔디안(Big endian)의 차이점 알아보기 pjk 2014.05.24 8653
18 Bit fields(비트필드) pjk 2014.05.24 4833
17 구조체 메모리 저장방식 #pragma pack file pjk 2014.05.24 5899
16 함수 포인터의 배열 pjk 2014.05.24 8638
15 void형 포인터 pjk 2014.05.24 6052
14 unsigned형의 모든 상수에는 접미사 ‘U’를 사용하여야 한다. file pjk 2014.05.24 38731
13 클래스 멤버에 대한 액세스 제어 pjk 2014.06.27 5504
12 strcmp, wcscmp, _tcscmp pjk 2014.07.18 11426
11 HEX(16진수) to ASCII(아스키) 변환 코드 pjk 2014.08.24 34939
» volatile이 정확히 어떤 의미를 가지는 건가요? pjk 2014.09.30 5458
9 c/c++문자열, 유니코드 관련 함수 makersweb 2015.07.09 6188
8 구조체 배열을 반환하는 함수를 반환하는 함수를 호출하여 구조체 멤버 배열 요소 접근하기 makersweb 2016.05.22 10825
7 switch와 if 중 어느 것이 더 빠른가 file makersweb 2017.01.31 3779
6 함수포인터와 typedef로의 선언 makersweb 2018.02.03 1974
5 싱글톤 객체생성 패턴에 대해서 file makersweb 2018.07.01 4500
4 배열과 포인터, 등가포인터 예제 makersweb 2019.01.16 1958
3 C++로 플러그인 개발 file makersweb 2019.12.08 2699