2009-12-23 60 views
7

我有以下代碼宏和函數同名

#define myfunc(a,b) myfunc(do_a(a), do_b(b)) 

void myfunc(int a, int b) 
{ 
    do_blah(a,b); 
} 
int main() 
{ 
    int x = 6, y = 7; 
    myfunc(x,y); 

    return 0; 
} 

我想預處理器僅在調用擴展功能MYFUNC。預處理後所需的代碼看起來是這樣的:

void myfunc(int a, int b) 
{ 
    do_blah(a,b); 
} 
int main() 
{ 
    int x = 6, y = 7; 
    myfunc(do_a(x),do_b(y)); 

    return 0; 
} 

的問題是,函數定義也擴大這樣

void myfunc(do_a(int a), do_b(int b)) 
{ 
    do_blah(a,b); 
} 

有沒有什麼辦法讓宏展開,只有當我們正在擴大功能呼叫? 我嘗試了許多解決方案,它似乎是不可能的,但我希望有人見過這樣的情況..

注:請不要告訴我重新命名宏或函數名:d

UPDATE1: 感謝您的幫助。但是我只能改變宏的定義,我不能改變它的位置,我不能改變函數的實現。

回答

15

使用()從擴展功能定義停止預處理:

#include <stdio.h> 

#define myfunc(a, b) myfunc(do_a(a), do_b(b)) 
/* if you have a preprocessor that may be non-standard 
* and enter a loop for the previous definition, define 
* myfunc with an extra set of parenthesis: 
#define myfunc(a, b) (myfunc)(do_a(a), do_b(b)) 
******** */ 

int (myfunc)(int a, int b) /* myfunc does not get expanded here */ 
{ 
    printf("a=%d; b=%d\n", a, b); 
    return 0; 
} 

int do_a(int a) 
{ 
    return a * 2; 
} 

int do_b(int b) 
{ 
    return b - 5; 
} 

int main(void) 
{ 
    myfunc(4, 0); 
    return 0; 
} 
+0

它的工作原理:) 謝謝 – Yousf 2009-12-23 13:57:56

+0

我認爲一些預處理器可能會妨礙myfunc(xxx,xxx)形式的遞歸使用。我會做 的#define MYFUNC(A,B)(MYFUNC)(do_a(一),do_b(B)) INT(MYFUNC)(INT A,INT B) &C – 2009-12-23 17:39:39

+2

好一點,蒂姆,謝謝!但我認爲假定預處理器永遠不會進入遞歸循環是安全的(參見標準6.10.3.4/2「...如果任何嵌套替換遇到被替換的宏的名稱,它不會被替換...」)。 – pmg 2009-12-23 18:11:31

0

定義函數後定義宏。

可替代地,使用一種模式是這樣的:

#define myfunc_macro(a,b) myfunc(do_a(a), do_b(b)) 
#define myfunc(a,b) myfunc_macro(a,b) 

. 
. 

#undef myfunc 
void myfunc(int a, int b) 
{ 
    do_blah(a,b); 
} 
#define myfunc(a,b) myfunc_macro(a,b) 

. 
. 

int main() 
{ 
    int x = 6, y = 7; 
    myfunc(x,y); 

    return 0; 
} 
3

定義函數的宏把定義。

void myfunc(int a, int b) 
{ 
    do_blah(a,b); 
} 

#define myfunc(a,b) myfunc(do_a(a), do_b(b)) 

int main() 
{ 
    int x = 6, y = 7; 
    myfunc(x,y); 

    return 0; 
} 
8

我看到三個可能的解決方案:

  • 定義後的函數定義宏。

  • 定義,函數定義之前,do_a()do_b(),使得他們返回自己的說法,後函數定義你的意志重新定義它們

  • 執行do_a()do_b()在函數內部:

    void myfunc(int a, int b) 
    { 
        do_blah(do_a(a),do_b(b)); 
    } 
    

我對後者有強烈的偏好。

0

爲什麼你不能更改源代碼?最壞的情況下,如果你需要維護原始版本,可以在其上運行一個patch來創建一個臨時文件,在該文件中重新命名該函數並從那裏構建它。

+0

是舊代碼..改變功能或宏的名字是不是一種選擇。 – Yousf 2009-12-23 13:58:43

+0

這是根本不可能的,你可以改變宏而不是功能。根本不可能編譯一個文件,但不能選擇要編譯的文件。你在說垃圾。 – 2009-12-23 15:04:36