2010年1月21日 星期四

[語言] __FILE__, __LINE__

上次在神人那看到....他說:我就是要挺慣C,
恩...
可以交到這麼多正妹的慣C,我也很挺XD

看過
__FILE__, __LINE__ 沒?

C語言常常有那種知道的不要問,不知道的不要說的詭異(取自某討論區的黑暗氣氛...這根本是死結嘛)





其實這是GCC complier 預先就定義好的變數,不只這兩個,只要符合C99的標準有以下七個
__LlNE__
__FILE__
__FUNCTION__
__TIME__
__DATE__
__STDC__           (是否遵守ISO C )
__STDC_HOSTED__  (是不是HOST,非寄居)
__STDC_VERSION__ (版本)

用GCC的話並不完全符合上面的定義
__STDC_VERSION__ 就變成 __VERSION__
__func__ 等同於__FUNCTION__ 不過聽說GCC建議使用前者。

另外complier,我用GCC試過存在
__TIMESTAMP__

寫個程式印一下就知道了
printf("line: %d \n", __LINE__);
printf("file: %s \n", __FILE__);
printf("function: %s \n", __FUNCTION__);
printf("function: %s \n", __func__);
printf("time: %s \n", __TIME__);
printf("date: %s \n", __DATE__);
printf("STDC: %d \n", __STDC__);
printf("STDC_HOSTED: %d \n", __STDC_HOSTED__);
printf("VERSION: %s \n", __VERSION__);
printf("TIMESTAMP: %s \n", __TIMESTAMP__);


輸出:
line: 150
file: test.c
function: main
function: main
time: 15:13:28
date: Jan 21 2010
STDC: 1
STDC_HOSTED: 1
VERSION: 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
TIMESTAMP: Thu Jan 21 15:13:26 2010

這東西就可以視情況取用,很方便。
多方便?

例如我們要重新定義一個DBG()函數來幫忙debug好了

#define DBG(msg, arg...) printf("%s:%s(%d): " msg, __FILE__, __FUNCTION__, __LINE__, ##arg)

這樣我們就可以把DBG()當作printf()使用還多增加function name 行數等等可以查詢。


DBG("index:%d str = %s\n", index, str);
輸出: test.c:main(146): index:2147483647 str = bejo

--
那define 看起來十分詭異對吧 XD
其實那也只是置換的意思,把置換ㄧ下就很清楚了

DBG("index:%d str = %s\n", index, str);

被置換成

printf("%s%s(%d): " "index:%d str = %s\n", __FILE__, __FUNCTION__, __LINE__,  index, str);

DBG --> printf
msg --> "index:%d str = %s\n"
arg --> index, str

就ㄧ點都不奇怪了...

補充一下假指令#line 的用法
這用法可以在openl2tp這包open source看到,用在bison paswer相關

例如當
testA.c 是由bejo.c 自動產生時,run testA.c包好的檔案去debug會產生一些困擾,這時候我們可以這樣做

#line 888 "bejo.c"
        printf("%s line: %d\n", __FILE__, __LINE__);
        printf("line: %d\n", __LINE__);

輸出
bejo.c line:888
line:889

就會知道該去看該死的bejo.c 第888行

---
自動產生的code聽起好夢幻XD