2010-09-03 46 views
6

我想要定義一個宏來生成一個包含變量的標記名稱。涉及變量的C宏令牌串聯 - 有可能嗎?

基本上,我想是這樣的:

​​

我希望能產生上述聲明令牌P2DIR,但根據我的編譯器的輸出,它生成令牌PportDIR,這是不是我想要的。這裏有幫助嗎?或者是我試圖做不可能的事情?

+0

你打算做'#define port 2'嗎? – Gabe 2010-09-03 04:40:16

回答

6

我不認爲你想要做什麼是可能的。 C宏是在編譯之前展開的預處理宏。變量port,直到運行時纔會被設置。

+0

謝謝,這正是我的想法。它已經有一段時間了,因爲我已經完成了直行C. – gatesphere 2010-09-03 04:50:22

3

這是不可能的。 C預處理器通過處理標記來工作,並且它們不做任何需要知道該語言機制的解析或替換(除了涉及整數文字的基本算術,不在我頭頂)。例如,考慮GCC預處理器regarding tokenisation的文檔。只有編譯器會知道如何處理變量「端口」。

一種解決辦法是做這樣的事情:

#define PxDIR(var, portnum) do { \ 
    var = portnum; \ 
    P##portnum##DIR |= blah; \ 
} while(0) 

......後來......

int port; 
PxDIR(port, 2); 

我讓你做這個不醜或哈克,因爲它是這裏(和更普遍的,這取決於你的需要):)

+0

謝謝。我正在研究它作爲一種減少嵌入式項目中代碼膨脹的方法,但它看起來好像不可能使用變量來解決這個問題。呃,好吧。再次感謝! – gatesphere 2010-09-03 04:52:27

+0

@ user438605事實上 - 儘管您可能想要查看[X Macro Idiom](http://www.drdobbs.com/184401387)以重複生成代碼。 – detly 2010-09-03 08:39:16

2

...或者只是做PORT也是宏:

#define PORT 2 
#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    PxDIR(PORT) |= 0x01; 
    return 0; 
} 
0

你試圖做的事情沒有意義。

​​

預處理器在編譯時(之前)運行。因此它無法知道變量port的內容。預處理器要求任何作爲宏參數傳遞的值都是常量。例如,你可以做到以下幾點:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    PxDIR(2) |= 0x01; //setup port 2 
} 

否則,如果你希望能夠給一個變量傳遞給這個宏真的是唯一的辦法就是確保明確生成的代碼可以這樣做:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

uint16_t* get_port_pointer(uint8_t port_id) { 
    if (port == 0) { 
    return &PxDIR(0); 
    } else if (port == 1) { 
    return &PxDIR(1); 
    } else if (port == 2) { 
    return &PxDIR(2); 
    } else if (port == 3) { 
    return &PxDIR(3); 
    } else { 
    return &0; 
    } 
} 

int main() { 
    int port; 
    port = 2; 

    *(get_port_pointer(port)) |= 0x01; 
} 

通過這種方式,我們確保存在從0到3的任何端口被訪問的代碼。另外,現在我們必須注意從get_port_pointer函數返回的空指針。