C語言巨集和函式淺析
預定義符號:
__FILE__:進行編譯的原始檔
__LINE__:檔案當前行號
__DATE__:檔案被編譯的日期
__TIME__:檔案被編譯的時間
define:
- #define定義識別符號:
#define MAX 1000;
1.如果定義的內容太長,可以分成幾行,但是每一行後面都要加上一個/(續行符)
2.define定義識別符號的時候最好不要在後面加上;這樣容易導致問題
- #define定義巨集:允許把引數替換到文字中
#define name(parament - list) stuff
注:左括號(必須與name緊鄰,如果倆者之間有任何空白,引數列表就會被解釋成stuff的一部分
#define SQUARE(x) ((x)*(x))
注:巨集定義時,一定不要吝嗇加括號,該加括號的地方都應加上,否則可能會出現錯誤
巨集引數和define定義中可以出現其他#define定義的變數,但是對於巨集,不能出現遞迴
##和#
字串有自動連線的特點
char *p = "hello""bit\n";
printf("hello""bit\n");
printf("%s\n", p);
如何把巨集引數插入到字串中?
1.將字串作為引數,
2.使用#,把巨集引數變成對應的字串
#define PRINT(FORMAT,VALUE)\
printf("the value of " #VALUE " is "FORMAT"\n", VALUE);
int main()
{
int i = 10;
PRINT("%d", i+3);
return 0;
}
//編譯器會把程式碼中的#VALUE預處理為“VALUE”
3.## 可以把位於它倆邊的符號合成一個符號,它允許巨集定義從分離的文字片段中建立識別符號
#define CAT(X,Y) X##Y
int main()
{
int val9 = 10;
printf("%d", CAT(val, 9));
return 0;
}
//輸出10,因為編譯器會將val和9連線在一起變成val9,等於=10
注:這樣的連線必須闡述一個合法的識別符號,否則其結果就未定義的
巨集和函式
命名約定:
巨集名全部大寫
函式名不要全部大寫
巨集通常用於執行簡單的運算,比如在倆個數中找大的一個
#define MAX(a,b) ((a)>(b)?(a):(b))
為什麼不用函式來完成這個任務呢?
- 用於呼叫函式和從函式返回程式碼可能比實際執行這個小型計算工作所需的實際更多,所以巨集比函式在程式規模和速度方面更勝一籌。
- 巨集和型別無關
巨集和函式相比其劣勢:
- 每次使用巨集的時候,就會將一份巨集定義的程式碼插入帶程式中。除非巨集比較短,否則可能大幅度增加程式的長度
- 巨集沒有辦法除錯
- 巨集和型別無關,不夠嚴謹
- 巨集可能會帶來運算子優先順序的問題,容易導致程式出錯
但是巨集也可以做一些函式做不到的事,比如巨集的引數可以事型別
巨集和函式的對比:
1.程式碼長度:
巨集:每次使用巨集的時候,就會將一份巨集定義的程式碼插入帶程式中。除非巨集比較短,否則可能大幅度增加程式的長度
函式:函式的程式碼只出現在一個地方,每次使用函式,都呼叫同一個地方的程式碼
2.執行速度:
巨集:趕快
函式:存在函式呼叫/返回的額外開銷
3.操作符的優先順序:
巨集:巨集引數要給他們加上括號,否則鄰近的操作符的優先順序可能會產生不可預料的結果
函式:函式只在函式呼叫的時候求值一次,他的結果值傳遞給函式,表示式的結果更容易預測
4.引數求值
巨集:引數每次都要重新求值,由於多次求值,具有副作用的引數可能會產生不可預測的結果
函式:函式只在函式呼叫的時候求值一次,引數的副作用並不會造成任何特殊的問題
5.引數型別:
巨集:巨集與型別無關,只要引數合法,它可以使用任何型別
函式:引數與型別有關,引數型別不同就要使用不同的函式,即使他們所做的任務相同
注:在c++中儘量不要用#define
- c++可以用const之間定義為常量‘
- c++可以用內聯(inline)
移除一個巨集定義:#undef
帶有副作用的巨集:
當巨集引數在巨集的定義中出現超過一次的時候,如果引數帶有副作用,那麼在使用這個巨集的時候就會出現危險,導致不可預測的結果。副作用就是表示式求值的時候出現的永久性效果
x+1;不帶副作用
x++;帶副作用
#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
reruen 0;
}
//輸出x=6,y=10,z =9;
//處理後z = (x++)>(y++)?(x++):(y++);
相關文章
- C語言有關函式淺析C語言函式
- C語言巨集中"#"和"##"的用法C語言
- C語言常用函式C語言函式
- C語言的函式C語言函式
- C語言 execve()函式C語言函式
- c語言巨集的使用C語言
- 08. C語言函式C語言函式
- C語言 函式指標C語言函式指標
- C語言基礎函式C語言函式
- C語言函式呼叫棧C語言函式
- 【C語言】函式的概念和函式的呼叫(引數傳遞)C語言函式
- 淺析stl仿函式函式
- C語言庫函式及示例C語言函式
- C語言函式sscanf()的用法C語言函式
- C語言qsort函式的使用C語言函式
- C語言解讀assert函式C語言函式
- C#語言函式遞迴C#函式遞迴
- 淺談C語言中函式的使用C語言函式
- C語言函式指標與回撥用函式C語言函式指標
- C語言語法基礎--S2函式和指標C語言函式指標
- C 語言回撥函式詳解函式
- c語言快速排序(庫函式使用)C語言排序函式
- c語言學習筆記===函式C語言筆記函式
- Julia1.0程式語言淺析
- C語言——設計printf除錯巨集C語言除錯
- c語言函式指標的定義C語言函式指標
- C 語言實現泛型 swap 函式泛型函式
- C語言中函式printf()和函式scanf()的用法C語言函式
- C語言函式指標與回撥函式使用方法C語言函式指標
- C語言-->(十四)結構體、巨集、編譯C語言結構體編譯
- Go 語言函式Go函式
- c語言是如何處理函式呼叫的?C語言函式
- C語言相關的基礎字串函式C語言字串函式
- C語言關於指標,gets()和gets_s()函式的理解C語言指標函式
- go語言入門之-函式和方法Go函式
- GO語言入門 - (六)函式和方法Go函式
- c/c++語言函式 stat, fstat, lstat, fstatat - get file statusC++函式
- 【C語言】常用的字串函式及相關函式的自我實現C語言字串函式