2009-07-24 71 views
2

我試圖在預處理器的幫助下改變C中的一些函數的行爲;並且還添加可進行設置或關閉可選參數......在編譯時的C函數裝飾器(包裝)

的可選參數的基本模式很簡單:

#ifdef OPT_PARAM 
    #define my_func(a, b, opt) _my_func(a, b, opt) 
#else 
    #define my_func(a, b, opt) _my_func(a, b) 
#endif 

/*the rest of the code always calls "my_func" with all the params 
and not the underscored version...*/ 

#ifdef OPT_PARAM 
void _my_func(int a, int b, int opt) 
#else 
void _my_func(int a, int b) 
#endif 
{ 
    /*... more #ifdefs surrounding opt uses */ 
} 

有條件地包裹的功能模式是相似的,但問題是下劃線開始加起來(每個嵌套層次額外增加一個,可以是不同的函數,或者只是在未包裝的情況下爲下一個層次定義一個#define)。

那麼,關於如何降低代碼複雜度的任何想法呢?

P.S.我願意使用Python ...但是這是一個驅動程序:-(

+0

你確定你不想要可變參數函數嗎? http://en.wikipedia.org/wiki/Varargs#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D – Inshallah 2009-07-24 15:59:58

+0

很確定我不想要他們!^_ ^我已經使用過它們,我非常擔心丟失靜態類型檢查。 – fortran 2009-07-24 16:02:19

回答

0

最後我剛添加的均勻處理額外的參數和更具描述性的名稱改變了晦澀下劃線一個新的裝飾。

現在,這是一個更正交的設計,我可以在編譯時插入和拔出行爲,而無需運行時間開銷。

2

似乎你想使用默認參數或C中不可用的東西。這似乎是一個壞主意。在多個C的方式,在這裏,如果你不想指定參數,你只是傳遞NULL或-1(標準)無法處理的東西。

​​
1

我覺得這可能是更接近你想要什麼,但我不確定,我的理解是允許具有任意數量參數的c函數,它們是類型檢查的,並且可以在編譯時被刪除。

讓我提醒您關於使用under通過引用標準來標識分數。您可能遇到保留的標識符。但是,我不知道這種可能性。

ISO/IEC 9899:1999(E)7.1.3

- 這與 下劃線和一個大寫字母 或其他下劃線開頭的所有標識符 總是保留用於任何用途。

此解決方案需要GCC。 GCC的版本也必須支持弱符號。這個想法是讓編譯器使用弱符號來尋找正確的函數定義。在沒有進一步的分析(GCC 4.x版肯定不會這樣)編譯時

if (0) { ... } 

:此外,該函數的內容是通過使用編譯器應該修剪枯枝的知識,即簡化。通過將不存在的可選參數定義爲c預處理器(cpp)符號,您可以避免在函數體中使用cpp條件(如果需要)。看看如何爲以下的f_opt0定義opt1和opt2。

#include <assert.h> 
#include <stdio.h> 

extern void f_opt0(int a, int b) __attribute__((weak)); 
extern void f_opt1(int a, int b, int opt1) __attribute__((weak)); 
extern void f_opt2(int a, int b, int opt1, int opt2) __attribute__((weak)); 

#ifdef OPT0 
void f_opt0(int a, int b) { 
#define opt1 0 
#define opt2 0 
#endif 
#ifdef OPT1 
void f_opt1(int a, int b, int opt1) { 
#define opt2 0 
#endif 
#ifdef OPT2 
void f_opt2(int a, int b, int opt1, int opt2) { 
#endif 
    if (opt1) printf("opt1=%d\n", opt1); 
    if (opt2) printf("opt2=%d\n", opt2); 
    printf("a+b=%d\n", a+b); 
    #undef opt1 
    #undef opt2 
} 

#define f(a, b, o1, o2) \ 
    if (f_opt2) f_opt2(a, b, o1, o2); \ 
    else if (f_opt1) f_opt1(a, b, o1); \ 
    else if (f_opt0) f_opt0(a, b); \ 
    else { assert(0 && "no f() defined!"); } 

int main(void) { 
    f(1, 2, 1, 1); 
    return 0; 
} 

我的測試是非常有限的,而且我不主張這是很好的設計C.這似乎容易出現的問題和麻煩理解。不過,我希望它能實現你的目標。

2

你可以使用C++編譯器嗎?你可以使用(的C++功能)只是函數重載。

另一種選擇是

#ifdef OPT_PARAM 
# define OPT(X) , X 
#else 
# define OPT(X) 
#endif 

int my_func(int a, int b OPT(int opt)) { 
#ifndef OPT_PARAM 
    int opt = default_value; 
#endif 
    ... // Rest of code 
} 


... 
// calling it 
my_func(2, 4 OPT(42));