C/C++預定義宏

來源:互聯網
上載者:User
下面描述的宏定義,不需引用其他標頭檔,直接可用於代碼中。特定的作用給我們提供了不少的便利。分別描述如下:

1 -- __FILE__,__LINE__,__FUNCTION__或者__func__

__FILE__:當前程式行所在源檔案名稱,標準C支援,該宏當做字串對待;
__LINE__:當前程式行所在源檔案內的行號,標準C支援,該宏當做整形對待;
__FUNCTION__或者__func__:當前程式行所屬的函數名稱,C99支援(如:VC++6.0不支援),該宏當做字串對待;

結合列印日誌功能,這些資訊將有助於調試。簡單的使用方法:

//將該程式儲存為test.cpp#include <iostream>using namespace std;int main(int argc, char *argv[]){printf("FILE:%s|LINE:%d|FUNCTION:%s|%s\n", __FILE__, __LINE__, __FUNCTION__, __func__);return 0;}

執行上述程式將列印:FILE:test.cpp|LINE:8|FUNCTION:main|main

特別說明,據參考資料中關於__func__的資訊稱,__func__不是一個宏,它是編譯隱式聲明的常量字元數組:static const char __func__[] = "function-name"。
2 -- __DATE__,__TIME__

__DATE__:當前檔案的編譯日期,格式是Mmm:dd:yyyy。該宏當做字串對待。

__TIME__:當前檔案的編譯時間,格式是hh:mm:ss。該宏當做字串對待。

編譯源檔案時,假如該宏,可以讓程式列印出編譯時間,達到區分不同版本的目的。簡單使用方法如下:

#include <iostream>using namespace std;int main(int argc, char *argv[]){printf("DATE:%s|TIME:%s\n", __DATE__, __TIME__);getchar();return 0;}

執行上述程式將列印:DATE:Oct 20 2010|TIME:23:33:24。不重新編譯器的情況下,每次執行該程式列印的都將是是這個時間,而不是系統的目前時間。這個時間要區別理解下。

3 -- #line

#line用於重設由__LINE__和__FILE__宏指定的行號和檔案名稱。比如說我們有這麼一個測試程式:

//將該程式儲存為test.cpp#include <iostream>using namespace std;int main(int argc, char *argv[]){#line 100 "baidu.cpp"printf("FILE:%s|LINE:%d\n", __FILE__, __LINE__);return 0;}

注釋掉第8行代碼,程式列印:FILE:test.cpp|LINE:9

不注釋第8行代碼,程式列印:FILE:baidu.cpp|LINE:100

可見:#line指定下行代碼的起始行號和源檔案名稱,範圍到檔案末尾或者再次#line的使用處。

4 -- __GUNC__

__GUNC__,是GCC編譯器的預定義,表明當前GNUC編譯的版本。__GNUC__ 的值表示gcc的版本,需要針對gcc特定版本編寫代碼時,可以使用該宏進行條件編譯。
6 -- 宏定義的"#"和"##"使用方法

"#":替換宏參數時,將其後面的宏參數轉換成帶引號的字串,例如:

#define STR(s) #sint main(){std::string str = STR(abcdefg);return 0;}

C編譯器在預先處理代碼時,第5行實際翻譯成:std::string str = "abcdefg";

"##":將該符號前後的兩個宏參數串連在一起,比如:

#define PRINT(PRINT_FUNNAME, VAR) print_##PRINT_FUNNAME(VAR)int main(){PRINT(common, 5);return 0;}

C編譯器在預先處理代碼時,第5行實際翻譯成:print_common(5);

我們實際看下綜合運用的例子:

//#include <iostream>#define PRINT(fun, name, var) print_##fun(#name, var)void print_common(const std::string & name, int var){std::cout << name << ":" << var << std::endl;}void print_tofile(const std::string & name, int var){char sz_temp[1024];memset(sz_temp, 0, sizeof(sz_temp));snprintf(sz_temp, sizeof(sz_temp), "%s:%d", name.c_str(), var);FILE * fp = fopen("./log.log", "w");fwrite(sz_temp, 1, strlen(sz_temp), fp);fclose(fp);}int main(){PRINT(common, age, 5);PRINT(tofile, age, 5);return 0;}

這個代碼的意思是,在主函數中以統一的調用入口"PRINT"該宏函數,通過制定不同的函數名稱,將變數的名稱和值列印到不同的地方,比如螢幕或者檔案中。
我們使用g++ -E marco.cpp預先處理命令查看下預先處理後的源檔案:

# 1 "marco.cpp"# 1 "<built-in>"# 1 "<command line>"# 1 "marco.cpp"void print_common(const std::string & name, int var){std::cout << name << ":" << var << std::endl;}void print_tofile(const std::string & name, int var){char sz_temp[1024];memset(sz_temp, 0, sizeof(sz_temp));snprintf(sz_temp, sizeof(sz_temp), "%s:%d", name.c_str(), var);FILE * fp = fopen("./log.log", "w");fwrite(sz_temp, 1, strlen(sz_temp), fp);fclose(fp);}int main(){print_common("age", 5);print_tofile("age", 5);return 0;}
7 -- 參考文檔&擴充閱讀

1/http://blog.csdn.net/chief1985/archive/2008/07/25/2711526.aspx

2/http://lukas06.blog.sohu.com/95352179.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.