2014-09-24 60 views
3

我想實現這樣的事情:陣列中的#define

#define MACRO(x) {PORTB=0,PORTC=0,PORTD=0} 

MACRO(0); //This would get replaced by PORTB=0; 
MACRO(1); //PORTC=0; 
MACRO(2); //PORTD=0; 

我想創建一個「宏陣列」。我會傳入一個索引,它會返回正確的代碼。

這可能嗎?

編輯:

如果有幫助,PORTB,PORTC和PORTD都是#define語句。

回答

5

它可以通過預處理器來完成,但它可以說是醜陋的。

#define MACRO_CASE0 PORTB = 0 
#define MACRO_CASE1 PORTC = 0 
#define MACRO_CASE2 PORTD = 0 

#define MACRO(X) MACRO_CASE##X 

也看看Boost.Preprocessor庫。 (它適用於C和C++)。

更新:後與Jonathan Leffler討論(見下文),我覺得有義務更新爲新的C程序員規勸答案不要濫用(強大的,但髒)技術如上所示。

如果你 - 作爲OP要求 - 想要傳遞給它的索引,它將返回正確的代碼,那麼你需要求助於預處理器編程。然而,如果你想要做的是執行基於某些條件的不同代碼,並且如果條件是編譯時常量,那麼希望它沒有運行時間開銷,那麼以下方法不僅更清潔,而且更多靈活,因爲它也允許傳遞運行時間值。現在

/* '#include' this definition in any file where you want to use it. */ 
static inline void 
do_the_right_thing(const int selector) 
{ 
    switch (selector) 
    { 
    case 0: 
     PORTB = 0; 
     break; 
    case 1: 
     PORTC = 0; 
     break; 
    case 2: 
     PORTD = 0; 
     break; 
    default: 
     assert(!"cannot do the right thing: invalid selector"); 
    } 
} 

,在你的代碼,如果你寫

do_the_right_thing(1); /* selector is a compile-time constant */ 

一個體面的編譯器優化適當啓用相比,使用宏將產生的開銷。但是,你也可以寫

do_the_right_thing(rand() % 3); /* selector is a run-time expression */ 

,編譯器會插入一些快速切換代碼選擇在運行時適當的操作。

+0

+1:與我的[答](http://stackoverflow.com/a/26019383/15168)相比,這有一個優點,它只能用於整數常量的參數;它也有缺點。 – 2014-09-24 14:32:29

+0

@JonathanLeffler真的,但誰會想用一個整數索引一個數組?如果你想,你也可以使用符號名稱。 – 5gon12eder 2014-09-24 14:34:43

+0

這取決於你是否想要動態選擇索引:'if(i> = 0 && i <= 2)MACRO(i);'或者類似的東西。如果它是一個微控制器,我懷疑你不想要那個,但是在代碼中我看不到'MACRO(1);'比'PORTC = 0'更清晰 - 實際上它少了很多對我清楚。但是,這可能部分地成爲問題的假象。如果宏背後的代碼是選擇PORTB,PORTC或PORTD中的一個用於賦值的LHS(因此用法是「MACRO(1)= 0」),那麼我建議不起作用 - 正如我的'不擴展或概括'評論。 – 2014-09-24 14:41:38

3

這將做任務,但它並沒有延長或概括很優雅:

#define MACRO(x) (((x) == 0) ? PORTB=0 : ((x) == 1) ? PORTC=0 : PORTD=0) 
+0

...並且效率不高(OP代碼看起來像某些微控制器的代碼)。 – 2014-09-24 14:25:19

+0

@MichaelWalz:什麼是低效?這是問題中顯示的示例的編譯時常量。首先這不是一個好主意,但它確實按照要求做了什麼。 – 2014-09-24 14:26:43

+0

實際上,它**效率很高,因爲編譯器會優化所有內容。宏MACRO(0)的預處理器輸出是(((0)== 0)?B = 0:((0)== 1)?C = 0:D = 0);' – 2014-09-24 14:40:14