支持C語言的平台有許多,常見的編譯器如VC、gcc、Clang等。不同的編譯器共同點是都支持標准C(ANSI C),但是各自卻又有自己獨立的、平台相關的功能以及函數接口。這通常為程序的移植性帶來很多問題。這裡我簡單談一下解決方案。
常見的解決跨平台移植的思路就是利用 宏。不同編譯器有各自不同的宏,宏有很多,具體可以參考編譯器的相關手冊。通過判斷一個宏是否存在來選擇性的包含頭文件或調用函數,其本質就是一種條件編譯。
比如一些平台相關的函數,在不同平台要包含不同文件。
#if defined __GNUC__
#include
#elif defined _MSC_VER
#include
#endif
#if defined 在本例中也可以用#ifdef 替換,但是如果是復雜的條件編譯(比如if後面同時判斷多個宏),就只能用#if defined 實現了。
__GNUC__
是在gcc編譯器中定義的宏,_MSC_VER
是Windows中VC編譯器中的宏。當然了你還可以選擇這兩個編譯器中的其他宏來實現這一功能,只要能確保是兩個編譯器中平台相關的宏就行。
_MSC_VER
這個宏還能判斷VC的版本。比如:
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
...
它的意思是如果VC的版本大於VC 6.0,那麼...
該宏的詳細參考,很容易百度到:
同樣的思路。我們也可以把條件編譯用在函數內部。比如要實現控制台的清屏功能,VC中的通常做法是這條語句system("cls")
;調用控制台的cls命令來清屏。而Linux環境下,給終端清屏是沒有cls這一命令的,取而代之的是clear命令。那麼如何實現跨平台的清屏功能呢?很簡單,依樣畫葫蘆:
void clear()
{
#ifdef __GNUC__
system("clear");
#elif defined _MSC_VER
system("cls");
#endif
}
這樣就有了跨平台的清屏函數clear。但是其實關鍵都是system函數,兩個平台都提供這個函數(system是標准 C裡面的函數)。所以可以再改一版。
#if defined __GNUC__
char *clear = "clear";
#elif defined _MSC_VER
char *clear = "cls";
#endif
...
//當需要清屏的時候
system(clear);
無論是gcc還是VC都有休眠函數,不過具體函數接口卻不同。
可見,兩種環境下的休眠函數的函數名並不相同。並且gcc的兩個sleep函數並沒有沒有提供毫秒級的分辨率。也就是說,比如要休眠200毫秒:
1秒=1000毫秒,1毫秒=1000微秒
那麼來實現一下跨平台的休眠功能,我提供一種我的方案:
#if defined __GNUC__
#include
#define Sleep(x) usleep(x##000)
#elif defined _MSC_VER
#include
#endif
這樣即使在gcc的編譯環境下,我們也有和VC中一樣的Sleep函數可以用了。這裡我是用宏函數來實現的。#define Sleep(x) usleep(x##000)
##是宏定義裡面的連接符,這樣就默認給參數後面多加了三個0,即擴大了1000倍。
gcc 的宏連接符(##)後面不支持連接+ - * /,所以不能寫成
#define Sleep(x) usleep(x##*1000)
不過VC支持##後面接+ - * /符號。
現在,來綜合一下剛才的兩個函數:清屏和休眠。寫一個擲骰子小游戲的demo。
#include
#include
#include
#ifdef __GNUC__
#include
char *clear = "clear";
#endif
#ifdef _MSC_VER
#include
char *clear = "cls";
#endif
int a[3];
//判斷是否為順子
int isShunzi()
{
int max=a[0],min=a[0],sum=a[0];
for(int i=1;i<3;i++)
{
if(a[i]>max)
max=a[i];
if(a[i]=11)
printf("您的點數是大\n");
else
printf("您的點數是小\n");
}