나는 컴퓨터 공학을 공부하고, 여기에 교사들은 항상이 같은 μC 주소를 정의라고 우리에게 이야기했다 :이 매크로 본문에 왜 형식 변환이 있습니까?
#define FIO0DIR (* (unsigned int *) 0x2009C000) //GPIO direction register from the lpc1769
하지만 그들은 정말 이유를 설명하거나 무슨 일이 일어나고 있는지 않습니다.
제 궁금한 점은 왜 캐스트가있는 것입니까?
나는 컴퓨터 공학을 공부하고, 여기에 교사들은 항상이 같은 μC 주소를 정의라고 우리에게 이야기했다 :이 매크로 본문에 왜 형식 변환이 있습니까?
#define FIO0DIR (* (unsigned int *) 0x2009C000) //GPIO direction register from the lpc1769
하지만 그들은 정말 이유를 설명하거나 무슨 일이 일어나고 있는지 않습니다.
제 궁금한 점은 왜 캐스트가있는 것입니까?
어째서 캐스트입니까?
0x2009C000
은 정수 상수이기 때문에. 주소가 아닙니다. C 유형 시스템은 대상 아키텍처가 아닐지라도 정수와 주소를 구별합니다. 여러 가지 제약 조건이있는 변환을 허용하지만 두 유형은 이 아니며이 하나입니다.
적분 상수를 올바른 포인터 유형으로 바꾸려면 캐스팅이 필요합니다. 따라서이를 역 참조하고 해당 주소에있는 항목에 액세스 할 수 있습니다.
인용 C11
, §6.5.3.2, 주소 및 간접 연산자
*
단항 연산자의 피연산자가 포인터 타입을 가진다. 그 자체에
는 0x2009C000
는 정수 상수 (§6.4.4.1 장에서 언급 한 바와 같이)이 아닌 포인터 타입이다.
그러나이 정수 상수를 주소으로 사용하려고하며 값을 얻기 위해 주소를 비준해야하므로 캐스트가 있습니다.
캐스팅로서 부호 INT 포인터를 정수 상수 값 취급하도록 컴파일러에 지시하고, 참조 연산자는 메모리 위치에 저장된 값을 얻기 위해 포인터에 작용한다.
일반 적용 가능성으로 간주하지 마십시오. 정수 상수 값이 (유효한) 주소 위치를 나타낼 수 있는지 여부는 플랫폼과 환경에 크게 좌우됩니다.
컨트롤러가 주소 0x2009C000에 매핑되어 있지만 조작하려면 해당 주소에서 저장하거나 읽을 데이터 형식을 정의해야합니다. 그리고 이것은 C와 같은 고급 언어에서 어떤 유형의 데이터가 어떤 주소에 저장되는지, 길이 (바이트) 및 표현 (예 : 2의 보수로 정수)을 지정하는 것입니다. 따라서 :
(unsigned int *)0x2009C000
은 부호없는 정수가 저장된 주소로 뷰 상수 0x2009C000을 의미합니다.
* ((unsigned int *)0x2009C000)
는 부호없는 정수는, 지정된 어드레스에 저장 단순히 부호 정수 변수 저장되는 어드레스에 저장된 변수를 의미한다.
이 코드는 깨졌습니다. '휘발성의 unsigned int *'이거나 더 나은'volatile uint32_t *'이어야합니다. 'volatile' 키워드는 하드웨어 레지스터에 대한 포인터를 선언 할 때 필수적입니다. – Lundin
아니요, 휘발성 키워드가 있어야합니다. 그렇지 않으면 결국 컴파일러가 이상한 최적화를 수행 할 수 있습니다. LPCXpresso는 gcc를 사용하며 gcc는 매우 적극적인 최적화 기능을 제공합니다. 아마 당신은 최적화가 비활성화되어 있기 때문에 작동합니다. '-O3'을 시도하고 버그가 튀어 나오는 것을 지켜보십시오. – Lundin
네 말이 맞아, 나는 최적화 옵션을 건드리지 않았고 분명히 -O0로 기본 설정되어있다. 이것이 지금까지 모든 것이 효과가 있었던 이유입니다. – Arrrow