預編譯宏比較
⑴ 宏和函數的區別
1/ 宏只是預編譯時一一展開,沒有類型檢查,可能產生二義性;同時宏寫的函數不容易直觀看懂。
#define MAX(a,b) ( (a)<(b)?(b):(a) )
2/ 內聯函數並不總是被內聯,inline對於編譯器不是強制性的,縞譯器根椐內聯函數代碼行數決定是否參於內聯,從編譯後生成的目標代碼大小就能看出到底編譯器是否真的內聯了,調用1次和調用2次目標代碼空間是不一樣的。
template<typename T>
inline void Count( const T& a, const T& b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
3/ 那麼我們就強置內聯好了,編譯時會出現什麼問題呢?
template<typename T>
inline __attribute__((always_inline)) void Count( const T& a,const T& b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
Test.h:25: sorry, unimplemented: inlining failed in call to 'void Count(const T&, const T&) [with T = int]': function body not available
// 說明模板不能參於強制內聯
4/ 去掉模板聲明,採取強制內聯是有效果的,並且隨著調用次數的增加目標代碼是不斷增大的,說明強制內聯起作用了,那它真達到宏的作用了嗎?
inline __attribute__((always_inline)) void Count( int a,int b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
5/ 那我們改一下再和宏比較, 調用強制Count版本兩次,沒有報變數c被重復定義,不知道為什麼? 難道可以獲取到每一次調用Count的函數地址嗎(實際GDB時就沒有Count函數的概念)? 如果調用宏版本的Count,是會報變數c被重復定義,簡單替換啦.
inline __attribute__((always_inline)) void Count( int a,int b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
#define Count(a,b) \
printf("always_inline?"); \
printf("always_inline?"); \
printf("always_inline?"); \
int c = a + b
⑵ 我想問一下C語言宏注釋和/* //注釋有什麼區別
預編譯與注釋是不一樣的概念。代碼文本在進行編譯時,首先排除了注釋。然後根據預編譯條件進行篩選排除或選擇分支。就象宏,編譯前首先替換宏,再進行編譯。預編譯和宏都是為了更高效率的代碼編寫和方便修改而存在的,不是為程序運行時准備的。
#if #endif 功能相當於if(){};只不過預編譯是在代碼編譯前已經選擇,條件選擇是在運行時進行選擇而已。
⑶ c++當中的預編譯宏的問題
#ifndef HY //一般在頭文件都都使用這種格式以防止頭文件在同一文件中被包含兩次。語名#ifndef hyong…..#endi表示僅當以前沒有使用預處理器編譯指令#define定義的名稱hyong時才處理#ifndef….#endif之間的語句。
#define HY //在這里用define定義一個名字HY,以便在下次訪問到該頭文件時,使該名字已經被定義,從而讓程序跳過#ifndef….#endif間的語句。
...
#endif
明白了??
如果還不明白,就下載本人的文章《C++名稱空間與作用域專題》和《C++宏,預處理器,RTTI,typeid與強制類型轉換》去了解了解吧。
⑷ C關於宏的計算
宏在預編譯的時候處理,包含#的指令,都是在預編譯的時候處理
相對於運行階段,你也可以認為是編譯階段。
它只是簡單的字元串替換,不是計算。
它不影響代碼的執行速度,但是可能會增加代碼的長度,影響最終生成的可執行文件的大小。
補充:
表達式(10/5)的計算,應該在運行的時候吧
無法通過編譯選項控制這個的。
⑸ Source Insight,某些文件出現「parse too complex」,如何解決
你要的一次性從文件導入的功能類似的功能是有的,按照你之前選擇的選項,
Options->Preferences->Languages->Project Specific Conditions
選擇後再看右下角有個"Scan Files"按鈕,這個是Source Insight嘗試自己通過查找來確定所有預編譯宏定義的數值(TRUE/FALSE),試了一下是好用的,但是具體能不能解決你的無法解析文件的問題不太確定。
如果還不能解決的話,最好針對這些個別文件注意一下在函數中的if等判斷條件內部和括弧處試用了預編譯指令導致Source Insight無法識別的情況。重新將這些預編譯指令調整到括弧的外面有時就能解決,我遇到你這種情況就是是這樣解決的。
⑹ C++,宏定義怎麼用
宏定義又稱為宏代換、宏替換,簡稱"宏"。
格式:
#define 標識符 字元串
其中的標識符就是所謂的符號常量,也稱為"宏名"。
預處理(預編譯)工作也叫做宏展開:將宏名替換為字元串。
掌握"宏"概念的關鍵是"換"。一切以換為前提、做任何事情之前先要換,准確理解之前就要"換"。
即在對相關命令或語句的含義和功能作具體分析之前就要換:
例:
#define Pi 3.1415926
把程序中出現的Pi全部換成3.1415926
⑺ 宏、函數、宏函數的區別
宏、函數、宏函數的區別
先說宏和函數的區別:
1. 宏做的是簡單的字元串替換(注意是字元串的替換,不是其他類型參數的替換),而函數的參數的傳遞,參數是有數據類型的,可以是各種各樣的類型.
2. 宏的參數替換是不經計算而直接處理的,而函數調用是將實參的值傳遞給形參,既然說是值,自然是計算得來的.
3. 宏在編譯之前進行,即先用宏體替換宏名,然後再編譯的,而函數顯然是編譯之後,在執行時,才調用的.因此,宏佔用的是編譯的時間,而函數佔用的是執行時的時間.
4. 宏的參數是不佔內存空間的,因為只是做字元串的替換,而函數調用時的參數傳遞則是具體變數之間的信息傳遞,形參作為函數的局部變數,顯然是佔用內存的.
5. 函數的調用是需要付出一定的時空開銷的,因為系統在調用函數時,要保留現場,然後轉入被調用函數去執行,調用完,再返回主調函數,此時再恢復現場,
這些操作,顯然在宏中是沒有的.
現在來看內聯函數:
所謂"內聯函數"就是將很簡單的函數"內嵌"到調用他的程序代碼中,只樣做的目的是為了避免上面說到的第5點,目的旨在節約下原本函數調用時的時空開銷.但必須注意的是:作為內聯函數,函數體必須十分簡單,不能含有循環、條件、選擇等復雜的結構,否則就不能做為內聯函數了。事實上,即便你沒有指定函數為內聯函數,有的編譯系統也會自動將很簡單的函數作為內聯函數處理;而對於復雜的函數,即便你指定他為內聯函數,系統也不會理會的。
函數和宏函數的區別就在於,宏函數佔用了大量的空間,而函數佔用了時間。大家要知道的是,函數調用是要使用系統的棧來保存數據的,如果編譯器里有棧檢查選項,一般在函數的頭會嵌入一些匯編語句對當前棧進行檢查;同時,CPU也要在函數調用時保存和恢復當前的現場,進行壓棧和彈棧操作,所以,函數調用需要一些CPU時間。
而宏函數不存在這個問題。宏函數僅僅作為預先寫好的代碼嵌入到當前程序,不會產生函數調用,所以僅僅是佔用了空間,在頻繁調用同一個宏函數的時候,該現象尤其突出。
1. 宏在編譯之前進行,即先用宏體替換宏名,然後再編譯的,而函數顯然是編譯之後,在執行時,才調用的.因此,宏佔用的是編譯的時間,而函數佔用的是執行時的時間.
這句分開解釋:
"" 宏在編譯之前進行,即先用宏體替換宏名,然後再編譯的,""
解釋:假設代碼中有這么一條宏定義:#define MAX_LEN 10(10是宏體, MAX_LEN 是宏名)則在編譯之前, 也就是在預編譯的時候會將代碼中所有出現MAX_LEN的地方替換成10後在進行下面的代碼編譯, 這種替換工作實在編譯之前進行的...
"" 而函數顯然是編譯之後,在執行時,才調用的""
解釋: 函數調用實在執行時才調用的這是顯然的, 因為只有執行時才能根據具體的條件決定調用哪個函數
""因此,宏佔用的是編譯的時間,而函數佔用的是執行時的時間. ""
解釋:有了上面的解釋,估計這句話也就知道了, 從他的這句話看書的作者把預編譯也算作編譯的一部分了...
2.宏的參數是不佔內存空間的,因為只是做字元串的替換,而函數調用時的參數傳遞則是具體變數之間的信息傳遞,形參作為函數的局部變數,顯然是佔用內存的.
同樣分開解釋:
"" 宏的參數是不佔內存空間的,因為只是做字元串的替換""
解釋:假設有這么個宏定義#define MAX(a, b) (a) > (b) ? (a) : (b) 代碼中所有出現(初定義外)MAX(a, b)的地方在預編譯以後都變成了 (a) > (b) ? (a) : (b)這個式子, 比如代碼中有c = MAX(1, 3)這樣的語句, 則在預編譯的時候就會變成c = (1) > (3) ? (1) : (3), 這是一種直接的替換, 不會產生中間變數, 所以也就不用為之分配空間 ...
"而函數調用時的參數傳遞則是具體變數之間的信息傳遞,形參作為函數的局部變數,顯然是佔用內存的."
解釋: 函數調用時需要為每個形式參數在棧上分配空間, 然後將實參的值拷貝進去, 在函數的內部用的都是這個形參, 當函數結束後形參的空間會被自動釋放掉, 這也是為什麼形參的改變無法改變實參的值的原因...
==================================================
宏: 內聯函數:
1.由預處理器處理 1.編譯器處理
2.對++/--操作有副作用 2.可能會被編譯器拒絕(不一定內聯)
3.難於調試 3.可能造成代碼膨脹
4.必定被展開
******************************************************************************************************
宏函數和函數的使用小結:
函數體量很小時,為了減小系統的開銷時間,可以使用宏函數,而函數體比較復雜(需要遞歸、循環、判斷、選擇等...)的情況下,使用函數來定義可以避免宏函數定義帶來的副作用。 宏函數是在程序編譯時進行簡單的字元替換,而函數是在程序生成後才進行調用,這時會佔用開銷時間(主程序函數保留現場,在子函數體中需要進行參數的傳遞--實參傳遞給形參以及調用完後形參的銷毀等步驟 ),因此宏函數佔用的編譯時的時間,而函數佔用的是執行時的時間。 因此在函數體量簡單的情況下,使用宏函數可以極大的提高程序的執行效率和系統開銷。
⑻ C++#if宏比較
可以比較,不過這樣寫代碼的可讀性不是很好
你可以這樣變通一下
#defineCONDITION_XXX(A==B)
#ifCONDITION_XXX
...
⑼ 宏和函數的區別是什麼
1/ 宏只是預編譯時一一展開,沒有類型檢查,可能產生二義性;同時宏寫的函數不容易直觀看懂。
#define MAX(a,b) ( (a)<(b)?(b):(a) )
2/ 內聯函數並不總是被內聯,inline對於編譯器不是強制性的,縞譯器根椐內聯函數代碼行數決定是否參於內聯,從編譯後生成的目標代碼大小就能看出到底編譯器是否真的內聯了,調用1次和調用2次目標代碼空間是不一樣的。
template<typename T>
inline void Count( const T& a, const T& b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
3/ 那麼我們就強置內聯好了,編譯時會出現什麼問題呢?
template<typename T>
inline __attribute__((always_inline)) void Count( const T& a,const T& b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
Test.h:25: sorry, unimplemented: inlining failed in call to 'void Count(const T&, const T&) [with T = int]': function body not available
// 說明模板不能參於強制內聯
4/ 去掉模板聲明,採取強制內聯是有效果的,並且隨著調用次數的增加目標代碼是不斷增大的,說明強制內聯起作用了,那它真達到宏的作用了嗎?
inline __attribute__((always_inline)) void Count( int a,int b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
5/ 那我們改一下再和宏比較, 調用強制Count版本兩次,沒有報變數c被重復定義,不知道為什麼? 難道可以獲取到每一次調用Count的函數地址嗎(實際GDB時就沒有Count函數的概念)? 如果調用宏版本的Count,是會報變數c被重復定義,簡單替換啦.
inline __attribute__((always_inline)) void Count( int a,int b )
{
printf("always_inline?");
printf("always_inline?");
printf("always_inline?");
int c = a + b;
}
#define Count(a,b) \
printf("always_inline?"); \
printf("always_inline?"); \
printf("always_inline?"); \
int c = a + b
⑽ C語言如何在預編譯階段比較字元串
#define dprint(expr) printf(#expr"=%d",expr)
int i=j=1;
dprint(i+j);//展開後為 printf("i+j""=%d",expr);