const와 const volatile의 차이점
volatile
새 값이 업데이트 될 때마다 변수를 선언하면 변수를
이렇게 선언하면 const
해당 변수의 값은 변경되지 않습니다.
그러면 위와 같이 const volatile int temp;
변수 temp
를 선언하는 용도는 무엇입니까 ?
다음과 같이 선언하면 어떻게됩니까 const int temp
?
로 표시된 객체 const volatile
는 코드에 의해 변경이 허용되지 않습니다 ( const
한정자 로 인해 오류가 발생 함 )-적어도 해당 특정 이름 / 포인터를 통해.
volatile
한정자 의 일부는 컴파일러가 개체에 대한 액세스를 최적화하거나 재정렬 할 수 없음을 의미합니다.
임베디드 시스템에서 이것은 일반적으로 하드웨어에서 읽고 업데이트 할 수있는 하드웨어 레지스터에 액세스하는 데 사용되지만 쓰기에는 의미가 없습니다 (또는 쓰기 오류 일 수 있음).
직렬 포트에 대한 상태 레지스터를 예로들 수 있습니다. 문자가 읽기를 기다리고 있는지 또는 전송 레지스터가 새 문자를받을 준비가되었는지 (즉, 비어 있음) 다양한 비트가 표시됩니다. 이 상태 레지스터를 읽을 때마다 직렬 포트 하드웨어에서 발생한 다른 작업에 따라 다른 값이 나올 수 있습니다.
상태 레지스터 (특정 하드웨어 사양에 따라 다름)에 쓰는 것은 의미가 없지만 레지스터를 읽을 때마다 하드웨어가 실제로 읽혀 지는지 확인해야합니다. 이전 읽기에서 캐시 된 값을 사용하면 t 하드웨어 상태의 변화에 대해 알려줍니다.
간단한 예 :
unsigned int const volatile *status_reg; // assume these are assigned to point to the
unsigned char const volatile *recv_reg; // correct hardware addresses
#define UART_CHAR_READY 0x00000001
int get_next_char()
{
while ((*status_reg & UART_CHAR_READY) == 0) {
// do nothing but spin
}
return *recv_reg;
}
이러한 포인터가로 표시되지 않은 경우 volatile
몇 가지 문제가 발생할 수 있습니다.
- while 루프 테스트는 상태 레지스터를 한 번만 읽을 수 있습니다. 컴파일러는 지시 한 내용이 변경되지 않을 것이라고 가정 할 수 있기 때문입니다 (while 루프 테스트에는 아무것도 변경할 수없는 루프 또는 루프 자체가 없음). UART 하드웨어에 대기중인 문자가 없을 때 기능을 입력하면 문자를 수신하더라도 멈추지 않는 무한 루프에 빠질 수 있습니다.
- 수신 레지스터의 읽기는 컴파일러에 의해 while 루프 이전으로 이동할 수 있습니다
*recv_reg
. 루프에 의해 변경 되었음을 나타내는 함수가 없기 때문에 루프에 들어가기 전에 읽을 수없는 이유가 없습니다.
volatile
예선 보장하지만 이러한 최적화는 컴파일러에 의해 수행되지 않습니다.
volatile
일반적으로 다른 스레드에 의해 "외부"에서 변경 될 수 있음을 알고있을 때 변수와 관련된 코드를 최적화하지 않도록 컴파일러에 지시합니다.const
프로그램이 변수 값을 수정하는 것이 금지되어 있음을 컴파일러에 알립니다.const volatile
당신의 인생에서 정확히 0 번 사용되는 것을 보게 될 매우 특별한 것입니다 (tm). 예상대로 프로그램이 변수의 값을 수정할 수 없지만 외부에서 값을 수정할 수 있으므로 변수에 대한 최적화가 수행되지 않음을 의미합니다.
변수가 const이기 때문에 두 시퀀스 포인트 사이에서 변경되지 않았을 수도 있습니다.
Constness는 값을 변경하지 않겠다는 약속이지 값이 변경되지 않을 것이라는 약속입니다.
일부 구성 변수가 부트 로더에 의해 업데이트 될 수있는 플래시 메모리 영역에있는 임베디드 애플리케이션에서이 기능을 사용해야했습니다. 이러한 구성 변수는 런타임 동안 '상수'이지만 휘발성 한정자가 없으면 컴파일러는 다음과 같이 최적화합니다.
cantx.id = 0x10<<24 | CANID<<12 | 0;
... 상수 값을 미리 계산하고 즉시 어셈블리 명령을 사용하거나 근처 위치에서 상수를로드하여 구성 플래시 영역의 원래 CANID 값에 대한 모든 업데이트가 무시됩니다. CANID는 const 휘발성이어야합니다.
C에서 const와 volatile은 유형 한정자이며이 두 가지는 독립적입니다.
기본적으로 const는 프로그램에서 값을 수정할 수 없음을 의미합니다.
그리고 휘발성은 값이 갑작스럽게 변경 될 수 있음을 의미합니다 (프로그램 외부에서 가능).
사실 C 표준은 const와 volatile 모두 유효한 선언의 예를 언급합니다. 예는
"extern const volatile int real_time_clock;"
여기서 real_time_clock은 하드웨어에 의해 수정 가능하지만 할당, 증가 또는 감소 할 수 없습니다.
따라서 우리는 이미 const와 volatile을 별도로 처리해야합니다. 게다가, 이러한 유형 한정자는 struct, union, enum 및 typedef에도 적용됩니다.
const와 volatile을 함께 사용할 수 있습니다. 예를 들어, 0x30이 외부 조건에 의해서만 변경되는 포트의 값으로 간주되는 경우 다음 선언은 우발적 인 부작용 가능성을 방지합니다.
const volatile char *port = (const volatile char *)0x30;
const
변수는 c 코드로 수정할 수 없으며 변경할 수 없음을 의미합니다. 이는 명령어가 변수에 쓸 수 없지만 그 값은 여전히 변경 될 수 있음을 의미합니다.
volatile
means that the variable may change at any time and thus no cached values might be used; each access to the variable has to be executed to its memory address.
Since the question is tagged "embedded" and supposing temp
is a user declared variable, not a hardware-related register (since these are usually handled in a separate .h file), consider:
An embedded processor which has both volatile read-write data memory (RAM) and non-volatile read-only data memory, for example FLASH memory in von-Neumann architecture, where data and program space share a common data and address bus.
If you declare const temp
to have a value (at least if different from 0), the compiler will assign the variable to an address in FLASH space, because even if it were assigned to a RAM address, it still needs FLASH memory to store the initial value of the variable, making the RAM address a waste of space since all operations are read-only.
In consequence:
int temp;
is a variable stored in RAM, initialized to 0 at startup (cstart), cached values may be used.
const int temp;
is a variable stored in (read-ony)FLASH, initialized to 0 at compiler time, cached values may be used.
volatile int temp;
is a variable stored in RAM, initialized to 0 at startup (cstart), cached values will NOT be used.
const volatile int temp;
is a variable stored in (read-ony)FLASH, initialized to 0 at compiler time, cached values will NOT be used
Here comes the usefull part:
Nowadays most Embedded processors have the ability to make changes to their read-only non-volatile memory by means of a special function module, in which case const int temp
can be changed at runtime, altought not directly. Said in another way, a function may modify the value at the address where temp
is stored.
A practical example would be to use temp
for the device serial number. The first time the embedded processor runs, temp
will be equal to 0 (or the declared value) and a function can use this fact to run a test during production and if sucessfull, ask to be assigned a serial number and modify the value of temp
by means of a special function. Some processors have a special address range with OTP (one-time programmable) memory just for that.
But here comes the difference:
If const int temp
is a modifiable ID instead of a one-time-programmable serial number and is NOT declared volatile
, a cached value might be used untill the next boot, meaning the new ID might not be valid untill the next reboot, or even worse, some functions might use the new value while other might use an older cached value untill reboot. If const int temp
IS declared voltaile
, the ID change will take effect immediately.
This article discusses the scenarios where you want to combine const and volatile qualifiers.
http://embeddedgurus.com/barr-code/2012/01/combining-cs-volatile-and-const-keywords/
We use 'const' keyword for a variable when we don't want to the program to change it. Whereas when we declare a variable 'const volatile' we are telling the program not to change it and the compiler that this variable can be changed unexpectedly from input coming from the outside world.
In simple terms, Value in 'const volatile' variable cannot be modified programmatically but can be modified by hardware. Volatile here is to prevent any compiler optimisation.
참고URL : https://stackoverflow.com/questions/4592762/difference-between-const-const-volatile
'Development Tip' 카테고리의 다른 글
유효성을위한 포인터 테스트 (C / C ++) (0) | 2020.10.06 |
---|---|
0 패딩 (선행 0)을 사용하여 int를 QString으로 변환 (0) | 2020.10.06 |
SQL Server의 모든 데이터베이스 파일에 대한 정보 나열 (0) | 2020.10.06 |
AngularJS의 경우 정의되지 않거나 null (0) | 2020.10.06 |
Gulp를 사용하여 동일한 디렉토리 내의 여러 파일 확장자 (0) | 2020.10.06 |