붤러타일? 발음하기 힘들다....
Volatile 변수
기본적으로 C/C++ 컴파일러는 최적화의 기능을 가지고 있습니다. 비효율적이거나 불필요한 연산은 생략하고 코드를 최적화 시킵니다.
변수를 선언할 때 앞에 volatile을 붙이면 컴파일러는 해당 변수를 최적화에서 제외하여 항상 메모리에 접근하도록 만듭니다.
사용 방법
- 기본적인 변수 사용
int a
,static int a
- Volatile 변수 사용
volatile int a
,static volatile int a
사용하는 이유
- 컴파일러에서
최적화
를 방지한다. - 후속 프로그램이 변수를 다룰때
레지스터가 아닌 메모리
에서 읽어오도록 한다. (임베디드일 경우) - 만약 16비트 마이크로 먼트롤러에서 32비트(int, long) 변수를 읽어오려면 두번에 걸쳐서 메모리를 읽어야 한다. 그 변수를 읽는 동안에 갑자기 값이 바뀔 수 있는데 읽히는 동안 비트를 못건드리게 해야한다.
코드
프로그래머의 의도와는 다르게 컴파일러가 최적화를 진행할 수 있다. 또한 임베디드 환경이라면 상황이 다를 수 있다.
C 소스코드
int main()
{
int i = 0;
while (i < 10)
i++;
printf("%d\n", i);
}
위와 같이 작성된 코드는 컴파일러의 최적화로 인해 어셈블리어로 아래와 같은 구조로 진행한다.
int main()
{
int i = 10; // while문 제거하고 10을 할당
printf("%d\n", i);
}
임베디드 소스코드
static int power;
void Power_ON_OFF()
{
power = 0;
while(power!=1);
}
위와 같은 코드는 아래와 같이 무한루프로 최적화 된다.
void Power_ON_OFF()
{
power = 0;
while(true);
}
하지만 만약에 power변수가 인터럽트
또는 하드웨어 장치의 레지스터
라면 다른 동작에 의해 값이 변경될 수 있다.
비주얼 스튜디오 테스트 (Release 모드)
- 아래의 소스코드를 VC++에서 돌려보면 동작시간이 대략 0.001초정도 된다.
입력이 10만
이고 시간복잡도는O(N^2)
이라서 최소 10초가 넘어야하지만 0.001초가 걸린다?- k++연산이 어느정도 예상되다보니
컴파일러
에서 연산을 제외하고 최적화 진행.
(일반적으로 알고리즘 문제를 풀때는 1억에 1초로 생각합니다.)
(개인 컴퓨터는 처리속도가 빠르기 때문에 대략 10억에 1초 정도 걸립니다.)
#include <stdio.h>
#include <vector>
#include <time.h>
using namespace std;
int start, end_t;
int k; //이 부분을 volatile int k로 선언시에 대략 10초 소요.
//volatile int k; //최적화 제외 변수
int main()
{
start = clock(); //1클럭 = 1ms
for (int i = 0; i < 100000; i++)
k++;
for (int i = 0; i < 100000; i++)
{
int j;
for (j = i + 1; j < 100000; j++)
{
k++;
}
}
end_t = clock();
printf("%.4fsec ", (double)(end_t - start)/1000);
return 0;
}
정확한 시간복잡도 계산값은 N + ( ( N * (N-1) ) / 2 )
입니다.