2012-02-16 43 views
3

我寫了一些硬件的特定代碼,在這裏我想用C宏的變量沒有,宏定義是這樣的: -論點C近拍

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1) if(a[MODE][RESOURCE1] != x1) || \ 
                   (a[MODE][RESOURCE1] != y1)) \ 
                 a[MODE][RESOURCE1]=x3; 

因爲有時候我可以有更多的再1個資源分配,如: -

#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) if(a[MODE][RESOURCE1] != x1) || \ 
                   (a[MODE][RESOURCE1] != y1)) \ 
                     a[MODE][RESOURCE1]=x3; 
                 if(a[MODE][RESOURCE2] != x1) || \ 
                   (a[MODE][RESOURCE2] != y1)) \ 
                 a[MODE][RESOURCE2]=x3; 

有什麼辦法,我可以寫一個宏,它涵蓋這兩種情況下,因爲它需要可變數目的參數?

我已經使用可變數量的參數,在宏的printf宏,但再怎麼我會解決這些爭論,由各自的名稱,例如,如果我修改宏定義,如:0-

#define VALIDA_RESOURCE_AND_ALLOCATE(MODE,.....) 

我將如何識別RESOURCE1,RESOURCE2?

+3

你「可以」但不要。你現在有什麼作品。我將重新定義第一個:#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2)VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1); VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE2)「,然後我將它們中的_both_包裝在'do {...} while(0)'中,這樣它們就像正確的語句一樣。 (此外,從來沒有你的宏用分號。) – 2012-02-16 16:16:25

+0

但在這種情況下,如果假設第一個宏失敗,我想退出,這是不可能的,除非我檢查它的返回值... – Viks 2012-02-16 16:51:25

+1

正如目前所寫,這些宏有任何返回值。 – 2012-02-16 17:05:02

回答

1

你的宏在它們中有很多重複的代碼。簡化它們有助於使解決方案更加明顯:

#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) do {\ 
    VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE1); \ 
    VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE2); \ 
} while(0) 

這裏,它更清晰,這僅僅是第一個宏的重複調用,同時通過參數列表進行迭代。

假設你知道這裏正在使用的數據類型將始終是一致的,你可以嘗試這樣的事情(未經測試和註銷我的頭頂部):

#ifdef HARDWARE_PLATFORM_A 
    static sometype args[] = { 
     RESOURCE1, 
     RESOURCE2, 
     /* ... etc, etc */ 
    }; 
#elif defined HARDWARE_PLATFORM_B 
    static sometype args[] = { 
     RESOURCE10, 
     RESOURCE11, 
     /* ... etc, etc */ 
    }; 
/* repeat for all hardware platforms */ 
#endif 

void initialization_function (void) { 
    int i; 
    for (i = 0; i < (sizeof(args)/sizeof(args[0])); ++i) { 
     VALIDATE_RESOURCE_AND_ALLOCATE(MODE, args[i]); 
    } 
} 

其中sometype是數據RESOURCE1,RESOURCE2等將使用的參數類型

鑑於您正在嘗試執行的操作的複雜性,您最好寫一個函數來執行迭代而不是宏。您仍然可以使用宏創建RESOURCE列表,但不要試圖讓預處理器爲您執行迭代。如果您需要避免函數調用的開銷(因爲您將其標記爲「嵌入」),則可以聲明函數inline,並且結果應該與使用宏一樣高效。然而,在這個過程中,你會獲得類型安全性的東西。

雖然它可能在技術上可能這樣做與宏,這將是一個討厭的黑客,最有可能帶來更多的問題,而不是利益。使用預處理器執行復雜的程序任務很少成功。

您擁有的另一種替代方法是使用代碼生成器,該代碼生成器從文件中獲取RESOURCE參數列表並生成包含初始化代碼的.c文件。代碼生成器將用比C預處理器更強大的語言編寫(幾乎所有腳本語言都可以在此使用)。雖然這可能不值得麻煩,除非你有一長串RESOURCE s。

0

你可以完成它的一種方法是不要傳遞可變數量的參數,但要堅持使用兩個參數,並使第二個參數成爲可用於初始化的列表。例如(尾隨反斜槓離開爲清楚起見):

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE, LIST) 
{ 
    int resources[] = LIST; 
    int count; 
    for(count = 0; count < sizeof(resources)/sizeof(int); count++) { 
     /* do stuff here for each resources[count] */ 
    } 
} 

然後你就可以簡單地調用它是這樣:

VALIDATE_RESOURCE_AND_ALLOCATE(MODE, { RESOURCE1, RESOURCE2 }) 

注:有對皮膚這隻貓,所以挑選的方法不止一種你最喜歡的答案,並與它一起去:-)

+0

這不是「分配」,那是「初始化」。請注意,初始化允許使用「{RESOURCE1,RESOURCE2}」,我懷疑這是您的意圖:單純的分配不允許這樣做。 – 2012-02-16 17:06:56

+0

好點;編輯感謝。 – 2012-02-16 17:10:01

+1

這不起作用,因爲預處理器會將'{RESOURCE1'和'RESOURCE2}'視爲兩個參數,而不是包含逗號的單個參數。 – 2012-02-16 18:37:44

0

這會太愚蠢? ;-)

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1,RESOURCE2)    \ 
if(a[MODE][RESOURCE1] != x1) || (a[MODE][RESOURCE1] != y1))      \ 
a[MODE][RESOURCE1]=x3;          \ 
if((RESOURCE1 != RESOURCE2) && (a[MODE][RESOURCE2] != x1) || (a[MODE][RESOURCE2] != y1))) \ 
a[MODE][RESOURCE2]=x3; 

和下面稱它爲單一資源

VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R1) 

和下面一樣兩個?

VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R2)