2010-02-04 4 views
3

누군가가 매크로 확장 순서를 제어/지정하는 방법에 대한 아이디어가있을 것으로 기대하고 있습니다. 여기 맥락입니다 ...매크로 확장 순서를 제어하는 ​​방법이 있습니까


// 32 bit increments, processor has registers for set, clear and invert 
#define CLR_OFF 1 
#define SET_OFF 2 
#define INV_OFF 3 


#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits 
//Now if I use this I can do it quite nicely with 
#define STATUS_LED 0x0040; 
SET(LATB, STATUS_LED); // LATB is port of the LED. 

실제로 말 기준으로 꽤 주위에 하드웨어를 이동 했어 그래서 그룹에 너무 같은 STATUS_LED와 LATB 정보를 결정


#define STATUS_LED_PORT LATB 
#define STATUS_LED_MASK 0x0040; 
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK 

//And I try to use it via 
SET(STATUS_LED); 

그러나 슬프게도, LATB, 0x0040은 SET 매크로의 인수 1로 전달됩니다. 그래서 비트 동안 사용하기 위해,


inline void SET(u32_t *reg, u32_t bits) { ((volatile u32_t *) (((u32_t)reg) + SET_OFF*4)) = bits; } 
//Change the STATUS_LED macro to 
#define STATUS_LED &STATUS_LED_PORT, STATUS_LED_MASK 
SET(STATUS_LED); //Works great! 

그러나 4 반대로 불행하게도 내 컴파일러는 레지스터를 설정하는 6 개 지시 함수를 인라인 및 원인에 대한 필요성을하지 않습니다 매크로로 사용하지 않을 경우이 방법이 제대로 작동 - 그것은 예측할 수 없습니다. 이 SET(##STATUS_LED)

현재 이동 내 솔루션은 두 개의 매크로 설정하고, SETRM을하는 것입니다 (마스크, 등록 설정) :

나는 매크로 첫째, 무엇인가 누군가가 STATUS_LED을 확장 할 수있는 방법을 알고 있습니다 바라고 하지만 난 SET에 대한 코드의 모양 때문에 ...


#define SETRM(reg,bits) ... 
#define SET(args) SETRM(args) //WHY WOULD THIS GET EXPANDED HERE?? 

그리고 마지막 해결책이 있어야 같은 느낌, 내 프로세서의 컴파일러가 매크로 N-인수를 지원하지 않습니다, 나는 놀 수있을 거라고 생각 그걸로 슬퍼하지만. (

시간 내 주셔서 대단히 감사 드리며 모든 생각을 고맙게 생각하며 앞으로 나아갈 수는 있지만 SET를 어디에서나 사용할 수 있다면 훨씬 더 깨끗합니다. 루트 이름은 항상 같은 경우

답변

4

교체 세트 방식으로 발생합니다. # 연산자 나 ##의 양쪽 끝에 나타나지 않는 모든 인수는 함수 스타일 매크로가 확장되기 전에가 아니라 완전히 대체 된 매크로로 확장됩니다.

즉, 하나의 매크로를 두 개의 매크로 인수가되게하려면 매크로와 같은 필수 기능이 확장되기 전에 한 번의 매크로 대체가 발생해야합니다.

이것은 매크로와 같은 두 번째 함수의 솔루션이 원하는 함수와 비슷한 매크로로 확장된다는 것을 의미합니다.

은 원래 SET 정의

#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits 

두 개의 잠재적 인 인수

#define STATUS_LED_PORT LATB 
#define STATUS_LED_MASK 0x0040; 
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK 

로 확장 매크로 주어진 즉 당신은 당신이 필요로하는 대체를 얻기 위해 다른 함수와 같은 매크로를 사용합니다.

이어서 SET2(STATUS_LED)은 다음과 같이 확장됩니다.SET 매크로에 충분한 인수가 아니기 때문에

SET(LATB , 0x0040;) 

*((volatile unsigned long*)(& LATB + 2)) = 0x0040; 

이 유효하지 않습니다; 인수가 확장되기 전에 매개 변수가 인수와 일치합니다. 내 컴파일러에서 오류가 발생합니다. 그 행동은 정의되지 않았다.

SET(STATUS_LED) 
1

당신은 사용할 수 있습니다 기능과 같은 매크로의 확장의 매개 변수

#define SET_COMPOSITE(root) SET(root##_PORT, root##_MASK) 
관련 문제