Programing

상수 및 휘발성으로 선언 된 포인터

lottogame 2020. 11. 24. 07:32
반응형

상수 및 휘발성으로 선언 된 포인터


읽는 동안 이러한 유형의 선언과 다음 줄을 발견했습니다.

const volatile char *p=(const volatile char *) 0x30;

p의 값은 외부 조건에 의해서만 변경됩니다.

나는 외부 조건이 무엇인지 이해하지 못한다. 또한 이러한 유형의 선언을 실제로 사용하는 것은 무엇 입니까?


const프로그램의 흐름이가 가리키는 어떤 수정하지 않을 것을 말한다 p. 포인터를 역 참조한 후 값을 수정하려고하면 컴파일 타임 오류가 발생합니다.

*p = 'A'; // will not compile

이것은 특히 강력한 계약이 아닙니다. 위치의 값은 다음이 0x30아닌 별칭이 아닌 상수 포인터를 통해 변경할 수 있습니다 p.

volatile char *q = 0x30;
*q = 'A'; // will compile

이 계약을 깨는 또 다른 방법은 constfrom 을 캐스팅하는 것 입니다 p.

*(volatile char *) p = 'A'; // will compile

volatile그러나, 다른 스레드는 커널 비동기 신호 처리기 또는 동일한 메모리 공간에 액세스 할 수있는 외부 장치에 의해 발생 될 수있는 변형을 배제하는 것이 아니다. 이렇게하면 컴파일러는 by p가리키는 값이 변경되지 않고 참조 될 때마다 메모리에서로드 된다는 잘못된 가정을 할 수 없습니다 .

/*
 The character at 0x30 will be read on every iteration,
 even if the compiler has proven that the program itself
 doesn't modify the value at that address.
*/
while (*p) {
    ...
}

컴파일러가 이러한 구조를 잘못 최적화하면 메모리에서 값을 한 번만로드 한 다음 레지스터에 유지하는 명령을 내 보냅니다. 레지스터는 본질적으로 독립적 인 사본이며 원래 위치에 대한 변경 사항은 거기에 반영되지 않으며 말할 필요도없이 이로 인해 매우 불쾌한 버그가 발생할 수 있습니다.


예를 들어 네트워크 카드의 읽기 전용 하드웨어 레지스터를 고려하십시오.

프로그램의 제어 범위 밖에서 변경 될 수 있으므로 컴파일러는 레지스터에 값을 캐시하거나 최적화 할 수 없습니다. 따라서 volatile.

그리고 읽기 전용이므로 쓰지 마십시오. 따라서 const.


먼저 C11표준, §6.7.3, 유형 한정자 의 예를 인용하겠습니다.

선언 된 객체

extern const volatile int real_time_clock;

하드웨어에 의해 수정 가능하지만 할당, 증가 또는 감소 할 수 없습니다.

또한 관련 각주 (134),

휘발성 선언은 메모리 매핑 된 입력 / 출력 포트에 해당하는 개체 또는 비동기 적으로 인터럽트하는 함수에 의해 액세스되는 개체를 설명하는 데 사용될 수 있습니다. 이렇게 선언 된 객체에 대한 작업은 표현식 평가 규칙에서 허용하는 경우를 제외하고 구현에 의해 "최적화"되거나 재정렬되지 않아야합니다.

즉, 변수 값은 하드웨어에 의해 (메모리 매핑을 통해) 수정할 수 있지만 "프로그래밍 방식으로"수정할 수는 없습니다.

여기에서 장점은 두 가지입니다.

  • 값이 사용될 때마다 메모리에서 읽혀지며 (캐싱이 허용되지 않음) 최신 업데이트 값 (업데이트 된 경우)을 제공합니다.
  • 은 프로그램에 의해 의도적으로 또는 의도하지 않게 변경 ( 덮어 쓰기 ) 될 수 없습니다 .

다음 과 같은 volatile 키워드 소개 문서를 사용할 수 있습니다 .

변수는 값이 예기치 않게 변경 될 때마다 휘발성으로 선언되어야합니다. 실제로는 세 가지 유형의 변수 만 변경할 수 있습니다.

  • 메모리 매핑 된 주변 레지스터
  • 인터럽트 서비스 루틴에 의해 수정 된 전역 변수
  • 다중 스레드 응용 프로그램 내의 전역 변수

과:

임베디드 시스템에는 일반적으로 정교한 주변 장치가있는 실제 하드웨어가 포함됩니다. 이러한 주변 장치에는 값이 프로그램 흐름에 대해 비동기 적으로 변경 될 수있는 레지스터가 포함되어 있습니다. 매우 간단한 예로 주소 0x1234에있는 8 비트 상태 레지스터를 고려하십시오. 0이 아닐 때까지 상태 레지스터를 폴링해야합니다. 순진하고 잘못된 구현은 다음과 같습니다.

UINT1 * ptr = (UINT1 *) 0x1234;

// Wait for register to become non-zero.
while (*ptr == 0);
// Do something else.

컴파일러가 다음과 같은 어셈블리 언어를 생성하기 때문에 최적화 프로그램을 켜면 거의 확실하게 실패합니다.

mov    ptr, #0x1234     mov    a, @ptr loop     bz    loop

const는 프로그램이 변수를 변경하지 않을 것이라고 말하지만 문서 외부 소스에서 언급했듯이 휘발성으로 인해 최적화되지 않습니다.


* const volatile char * p = (const volatile char ) 0x30;
의미 : p의 값은 외부 조건에 의해서만 변경됩니다.

Conceptually, you can think of this type of variable as a logical viewer. Similar in concept to the peephole in a door. A peephole allows you to view what is on the other side of the door, but does not allow you to change what is on the other side (const). However, conditions on the outside of the door can change on their own volition (they are volatile). You can see what happens, but you cannot change what happens.

In an embedded system, for example, there are hardware registers designed to provide state information about events happening in the outside world. An optical encoder, for example, used to sense RPM will set a value in a register. Each rotation, it senses light from an led and modifys the value in a hardware register. This is what is meant by external conditions. On the other side of the picture, i.e. in your code (perhaps a PID control loop), you can read this information to use in providing adjustments to the loop, but you cannot change this value, nor would you want to. (const)

From the perspective of your software then, this illustrates:

enter image description here


const doesn't make a variable constant. It just make the compiler refuse some write access. This is still possible to write in the variable (via const-casted pointers for instance).

You can see const as a protection against coding mistakes.

This declaration make sure you don't inadvertently write to p, while telling the compiler not to optimize accesses (cache, out of order execution(?),...) because an external event may write in p.

참고URL : https://stackoverflow.com/questions/31456274/pointer-declared-as-constant-as-well-as-volatile

반응형