휘발성 변수를 선언한다는 것은 무엇을 의미합니까? volatile 키워드를 사용하지만 배경에서

많은 저수준 프로그램은 메모리 매핑과 같은 유형에 volatile 키워드를 사용하지만 배경에서 실제로 하는 일에 대해서는 혼란 스럽습니다 . 다시 말해, 컴파일러가 메모리 주소를 “최적화”하지 않을 때의 의미는 무엇입니까?



답변

volatile 다른 프로세서 또는 I / O 장치 또는 무언가가 변수를 변경할 수 있음을 의미합니다.

일반적인 변수를 사용하면 프로그램 단계 만 변경됩니다. 예를 들어 5변수 를 읽고 변경하지 않으면 여전히을 포함합니다 5. 그것에 의존 할 수 있기 때문에 프로그램은 다음에 변수를 사용할 때 변수를 다시 읽는 데 시간을 들일 필요가 없습니다. C ++ 컴파일러는을 기억하는 코드를 생성하는 것이 현명합니다 5.

그러나로 읽을 수 있으면 5시스템이 디스크에서 해당 메모리로 데이터를로드하여로 변경합니다 500. 프로그램이 새로운 값을 읽도록 500하려면 이전에 읽은 사용에 대해 너무 똑똑하지 않은 컴파일러가 필요합니다 5. 매번 값을 다시로드하도록 지시해야합니다. 그게 뭐야 volatile.

5 살짜리 아이들의 비유
큰 종이를 테이블 위에 올려 놓았다고 가정 봅시다. 논문의 한 구석에 진행중인 게임의 현재 점수를 기록합니다 3 to 4. 그런 다음 테이블 반대편으로 가서 게임에 대한 이야기를 쓰기 시작합니다. 게임을보고있는 친구가 게임이 진행됨에 따라 해당 코너의 점수를 업데이트합니다. 그녀는 지우고 3 to 4씁니다 3 to 5.

게임 점수를 스토리에 넣으면 다음 중 하나를 수행 할 수 있습니다.

  1. 마지막으로 읽은 점수를 적어 두거나 3 to 4변경하지 않았다고 가정하거나 적어 두십시오.
  2. 현재 점수를 읽으려면 표 반대편으로 3 to 5걸어가십시오. 이것이 volatile변수의 작동 방식입니다.

답변

volatile 두 가지 의미 :

  1. 변수 값은 코드를 변경하지 않고 변경 될 수 있습니다. 따라서 컴파일러가 변수 값을 읽을 때마다 변수를 마지막으로 읽은 시간과 같거나 마지막으로 저장된 값과 같다고 가정 할 수 없지만 다시 읽어야합니다.

  2. 휘발성 변수에 값을 저장하는 행위는 외부에서 관찰 될 수있는 “부작용”이므로 컴파일러는 값을 저장하는 행위를 제거 할 수 없습니다. 예를 들어 두 개의 값이 한 행에 저장된 경우 컴파일러는 실제로 값을 두 번 저장해야합니다.

예로서:

i = 2;
i = i; 

컴파일러 숫자 2를 저장하고 변수 i를 읽고 읽은 변수를 i에 저장해야합니다.

또 다른 상황이 있습니다. 함수가 사용 setjmp하고 longjmp호출되면 함수의 모든 휘발성 로컬 변수는 마지막 값이 저장되도록 보장됩니다. 이는 비 휘발성 로컬 변수의 경우에는 해당되지 않습니다.


답변

추상 설명
C와 C ++는 모두 추상 기계 라는 개념을 가지고 있습니다 . 코드가 일부 변수의 값을 사용할 때 추상 기계는 구현에서 해당 변수의 값에 액세스해야한다고 말합니다. 양식의 코드는 statement_A; statement_B; statement_C;지정된 순서대로 실행해야합니다. 이 세 가지 진술에 공통적 인 표현은 발생할 때마다 다시 계산해야합니다.

추상 머신에 따라, 일련의 명령문이 주어지면 statement_A; statement_B; statement_C;구현은 먼저 statement_A전체를 수행 한 다음 statement_B마지막으로 수행해야합니다 statement_C. 구현시 age5 값을 할당했음을 기억할 수 없습니다 . 참조하는 모든 명령문 age은 대신 해당 변수의 값에 액세스해야합니다.

volatile추상 시스템 사양에 따라 구현에서 C 또는 C ++ 코드를 엄격하게 실행하는 경우 키워드 가 필요하지 않습니다 . C 및 C ++ 추상 머신에는 레지스터 개념이없고 공통 하위 표현식 개념이 없으며 실행 순서가 엄격합니다.

두 언어 모두 as-if 규칙이 있습니다. 구현은 추상 시스템 사양에 따라 작업을 실행 한 것처럼 동작하는 한 표준을 준수 합니다. 컴파일러는 비 휘발성 변수가 할당간에 값을 변경하지 않는다고 가정 할 수 있습니다. as-if규칙을 어 기지 않는 한 , statement_A; statement_B; statement_C;일부 statement_C, 일부 statement_A, 전체 statement_B, 나머지 statement_A및 마지막으로 나머지를 실행 하여 시퀀스를 구현할 수 있습니다 statement_C.

이러한 as-if 규칙은 volatile변수에 적용되지 않습니다 . volatile변수와 함수 와 관련하여 구현은 사용자가 지시 한대로 정확하게 수행해야합니다.

추상 기계 사양에는 단점이 있습니다. 느립니다. 다른 언어에 비해 C 및 C ++의 한 가지 긍정적 인 측면은 언어가 매우 빠르다는 것입니다. 이러한 추상 시스템마다 코드가 실행 된 경우에는 그렇지 않습니다. 로-경우 규칙은 C 및 C ++ 너무 빨리 될 수 있도록 무엇인가.

ELI5 답변

컴파일러가 메모리 주소를 “최적화”하지 않을 때의 의미는 무엇입니까?

메모리 주소 “최적화”는 고급 개념으로 5 살짜리 기능의 영역에 속하지 않습니다. 준수하는 다섯 살짜리 아이들은 더 이상, 더 이상,하지 말라고 정확하게 행동 할 것입니다. 을 사용 volatile하면 구현이 5와 같이 작동하도록 지시합니다. 생각하지 않고 멋진 최적화가 없습니다. 대신 구현시 코드에서 지시 한대로 정확하게 수행해야합니다.


답변

(비) 휘발성은 컴파일러가 생성 한 어셈블리 코드 관점에서 코드를 최적화하는 방법에 대한 힌트입니다.

  • 비 휘발성 은 현재 컴파일러가 변수의 위치 또는 변수의 값을 서브 루틴으로 teranfered하는 방법을 결정 함을 의미합니다.
    • 고정 된 메모리 주소에서
    • 스택에서 [프로세서 현재 스택 포인터와 관련하여]
    • 힙에서 [프로세서 현재 기준점에 상대적]
    • 프로세서 레지스터에서
  • volatile 은 main-cpu-s 컨트롤 이외의 다른 것 (예 : 별도의 io-processer)이이 값을 변경할 수 있기 때문에 컴파일러가 변수를 최적화 할 수 없음을 의미합니다.

답변

대답은 꽤 일관성이 있지만 중요한 요점이 없습니다. 컴파일러에게 공간을 할당하고 모든 액세스에 대해 읽기 또는 쓰기를 읽고 해당 액세스를 수행하길 원한다고 알려주고 있습니다. 우리는 어떤 이유로 액세스 또는 변수를 최적화하는 것을 원하지 않습니다.

그렇습니다. 다른 사람이 우리를 위해 그 가치를 바꿀 수 있기 때문입니다. 또 다른 이유는 우리가 다른 사람을 위해 그 가치를 바꿀 수 있기 때문입니다. 다른 사람이 우리를 위해 그것을 바꾸거나 다른 사람이 하드웨어 / 논리 또는 소프트웨어 일 수 있습니다. 베어 메탈 임베디드 프로그램에서 하드웨어에 쓰거나 읽을 때 제어 및 상태 레지스터에 대한 액세스를 정의하는 데 종종 사용됩니다. 소프트웨어와 대화하는 소프트웨어뿐만 아니라 다른 답변에서 설명했습니다.

또한 코드 섹션의 시간을 정하려고 할 때 액세스가 언제, 어떤 순서로 액세스되는지 제어하는 ​​데 휘발성이 사용되는 것을 볼 수 있으며 문제의 변수 (시작 시간, 종료 시간 및 차이) 만 휘발성을 사용하지 않아야합니다. 컴파일러는 끝 부분 근처에서 계산되어 시간 측정 중 하나를 자유롭게 이동할 수 있습니다 (우리가 배치 한 위치가 아니라).

때때로, 당신은 단순히 시간을 태우는 데 사용되는 것을 보게 될 것입니다. 맨발의 야광 세계 인 초등 led 깜박임은 인간의 눈이 led를 볼 수있는 시간을 태우기 위해 변수에 휘발성을 사용할 수 있습니다. 상태를 변경하십시오. 타이머 나 다른 이벤트를 사용하여 시간을 소모하는 고급 예제