在我的C項目中我有五個不同的函數(具有相同的名稱),它們以不同的方式實現一個算法。在編譯時,我只需要選擇其中的一個函數。 我可以使用#define
和一堆#ifndef
來實現嗎?有沒有更好的方法來做到這一點?在編譯時選擇一個函數
回答
可能是一個更優雅的方法是用5個不同的名稱(例如F1,F2,F3,F4,F5)定義它們,但總是調用使用相同的不同名稱的功能(例如F)。然後編譯類似的東西:
gcc -Df=f1
這將編譯任何調用f()作爲調用f1()。
在C中,這是我知道這樣做的唯一途徑。 C++你會很幸運。
ifndef宏在編譯時似乎是唯一的可能性。
您可以在運行時嘗試使用函數ptrs。
只是認爲你可以創建不同的文件中的每個功能,並連接適當的一個,只要你想。沒有宏,只是一個Makefile開關。這樣你保持相同的簽名並在鏈接時決定使用哪個實現。鏈接algo1.o或鏈接algo2.o ...
是的。你要做的就是在代碼中這樣說:
#if defined(FUNC1)
...func1 here
#elif defined(FUNC2)
...func2 here
...ect. ect.
#endif
然後當你編譯添加例如gcc的選項-DFUNCX:
gcc -DFUNC1 -o myprogram myfile.c
然後你可以選擇哪些功能通過改變來編譯值放在-D選項中。這是非常普遍的做法。
一個小問題是,它可以調用如果您意外地同時定義了FUNCx和FUNCy,則可以使用多種功能。要解決這個問題,你應該使用「#if defined(FUNC1)」,「#elif defined(FUNC2)」等。 – 2009-10-28 22:40:56
好點;我的錯。現在編輯代碼以反映這一點。 – 2009-10-28 22:45:14
如果我是你,我會擁有5種不同的函數名,然後使用if語句來找出在運行時調用哪一個。
C沒有重載(操作符或其他),所以沒有其他方法來做到這一點。恐怕你被預處理器命令困住了。
您不能在一個翻譯單元中定義具有相同名稱的兩個不同功能。
所以我想你已經有不同的源文件分開的功能。只要有你想要的文件,當您編譯...例如,用gcc
gcc -o testsort main.c bubble.c
gcc -o testsort main.c merge.c
gcc -o testsort main.c radix.c
凡有任何的bubble.c
,merge.c
,radix.c
(和其他人)具有相同名稱的功能:
int sort(int *data, size_t len) { /* ... */ }
如果你有單獨文件中的函數源(對於我的例子,在f1.c和f2中。C),那麼這個方案的工作原理:
$ cat so.c
#define STRINGIZER(x) #x
#define HEADER(x) STRINGIZER(x)
#include HEADER(SOURCE)
int main(void)
{
return(function());
}
$ cat f1.c
static int function(void)
{
return(1);
}
$ cat f2.c
static int function(void)
{
return(2);
}
$
然後,我可以這樣進行編譯:
$ gcc -DSOURCE=f1.c -o so1 so.c
$ gcc -DSOURCE=f2.c -o so2 so.c
注意使用stringize運營商和雙宏觀舞蹈 - 這是爲一個標準的成語標準C預處理器。它允許我避免在C編譯器命令行中放置引號;認爲這將是多麼更難使用,如果你有寫:
$ ./so1; echo $?
1
$ ./so2; echo $?
2
$
這顯示了一種替代的方式來實現,沒有任何希望的結果:
$ gxx -DSOURCE='"f1.c"' -o so1.c
是正在運行的S01和S02的結果#ifdef
行。
如果你一定要堅持使用C,你可以使用函數指針,但我會建議你使用C++和多態,這將讓你你的煩惱:)
- 1. 在編譯時選擇使用模板調用哪個函數
- 2. C++編譯器選擇一個類的成員函數
- 3. 如何在編譯時選擇函數行爲?
- 4. 在編譯時選擇/發現extern函數調用的簽名
- 5. 在運行時編譯函數C++編譯時編譯的函數的數量
- 6. 在編譯時選擇實現在F#
- 7. 編譯如何選擇調用哪個模板函數?
- 8. Go - 編譯一組函數時出錯
- 9. 在CUDA中有選擇地編譯頭文件和類函數
- 10. 在編譯時將一個泛型類傳遞給函數
- 11. 編譯時純虛函數
- 12. C++編譯錯誤只有一個候選函數
- 13. 編譯時檢查jQuery選擇器
- 14. 在編譯時生成函數
- 15. JAVA \僅在運行時編譯函數
- 16. 如何在運行時編譯函數?
- 17. 可選參數「必須是一個編譯時間常數」
- 18. Python編譯器函數在編譯時調用
- 19. 如何在Automake中選擇一個編譯器版本?
- 20. 在終端中編譯Xcode項目 - 選擇另一個Xcode
- 21. 在QComboBox中選擇一個新項目時運行函數
- 22. 「TypeError:$(...)。timepicker不是一個函數」在jquery時間選擇器
- 23. 在不同的編譯器中定義一個彙編函數
- 24. 編譯器如何選擇正確的函數?
- 25. 爲什麼C++編譯器(VS2013)選擇錯誤的函數?
- 26. SQL 2005 - 表值函數編譯確定,但選擇
- 27. SqlParameter構造函數編譯器超載選擇
- 28. 編譯器選擇了仿函數同名
- 29. 哪個Android SDK選擇編譯
- 30. 如何在編譯時在C#中運行一個函數或一段代碼
+1爲避免無盡的#ifdef的。無論如何編譯器會優化未使用的函數。 – 2009-10-28 22:44:31
編譯器應該優化它,但實際上呢? (只讀這讓我想知道:http://utilitybase.com/article/show/2007/04/09/225/Size+does+matter:+Optimizing+with+size+in+mind+with+GCC) – 2009-10-28 23:02:21
如果函數被聲明爲靜態,它可能無法編譯 – eyalm 2009-10-29 03:04:41