【1】宏定義怎么理解?
? ? ? ?關于宏定義,把握住本質:僅僅是一種字符替換,而且是在預處理之前就進行。
【2】宏定義可以包括分號嗎?
? ? ? ?可以,示例代碼如下:
1 #include<iostream>
2 using namespace std;
3
4 #define PI 3.14; //宏定義可以包括“;”
5
6 void main()
7 {
8 double r=10,s;
9 s=r*r*PI //注意此處的語法
10 cout<<s<<endl; //314
11 }
【3】宏定義一種新類型如何實現?
? ? ? ?示例代碼如下:
1 #include<iostream>
2 using namespace std;
3 #define int int *
4 void main()
5 {
6 int a,b;// int *a, b;
7 }
8 //理解此處的微妙:int *a,b; 這條語句同時定義了兩個變量。一個指針:int *a; 一個變量:int b;
【4】宏定義一個函數如何實現?
? ? ? ? 示例代碼如下:
1 #include<iostream>
2 using namespace std;
3
4 #define Begin() {int a;a=0;cout<<"a="<<a<<endl;}
5
6 void main()
7 {
8 Begin()
9 }
10 //如果{......}中的代碼太多,應該使用宏連接
11 //代碼如下所示:
12 #define Begin() { int i;\
13 i=10;\
14 cout<<"i="<<i<<endl;}
【5】宏定義如何取消?
? ? ? ? 示例代碼如下:
1 #include<iostream>
2 using namespace std;
3
4 #define int int *
5
6 void main()
7 {
8 int a, p; // int *a,p;
9 a = &p;
10 #undef int //取消宏定義
11 int b = 10;
12 a = &b;
13 }
?【6】對宏定義歧義現象怎么識別?
? ? ? ? ?示例代碼如下:
1 #define SUM(x,y) x*y
2 #define SUMM(x,y) ((x)*(y))
3 void main()
4 {
5 int a = 4, b = 5;
6 cout<<SUM(a+2,b+4)<<endl; //18
7 cout<<SUMM(a+2,b+4)<<endl; //54
8 }
? ? ??求一個數的平方正確的宏定義:
#define S(r) ((r)*(r))
? ? ?這個宏定義注意事項:
? ? (1)宏名和參數的括號間不能有空格
? ? (2)宏替換只作替換,不做計算,不做表達式的求解
? ? (3)函數調用在編譯后程序運行時進行,并且分配內存。宏替換在編譯前執行,不分配內存
? ? (4)宏的啞實結合不存在類型,也沒有類型轉換
? ? (5)函數只有一個返回值,利用宏則可以設法得到多個值
? ? (6)宏展開使源程序變長,函數調用不會
? ? (7)宏展開不占運行時間,只占編譯時間,函數調用占運行時間(分配內存 保留現場 值傳遞 返回值)
? ? ??何謂啞實結合?
? ? ? 示例代碼及解釋如下:
1 #define S(a,b) a*b
2 void main()
3 {
4 int area = 0;
5 area = S(3,2); //第一步:被替換為area = a*b; 第二步:被替換為area = 2*3;
6 //類似于函數調用,有一個啞實結合過程
7 }
?【7】下面宏定義特例如何解析?
? ? ? ? ?示例代碼如下:
1 #define NAME "zhangyuncong"
2 //#define AB "liu //error!!編譯錯誤
3 //#define 0x abcd //error!!編譯錯誤
4 void main()
5 {
6 cout<<NAME<<endl; //zhangyuncong
7 cout<<"NAME"<<endl; //NAME
8 cout<<"NAMElist"<<endl;//NAMElist
9 //cout<<NAMEList<<endl; //error!!!!編譯錯誤
10 }
? ? ? ?也就是說,這種情況下記住:#define ? ?第一位置 ? ??第二位置
? ? ? (1)不替換程序中的字符串內的任何內容
? ? ? (2)第一位置只能是合法的標識符(可以是關鍵字)
? ? ? (3)第二位置如果有字符串,必須把“”配對
? ? ? (4)只替換與第一位置完全相同的標識符
? ? ? ? 總之一句話:僅僅只是簡單的替換而已,不要在中間計算結果,一定要替換出表達式之后再計算
?【8】宏定義的特例有參形式如何解析?
? ? ? ? ?示例代碼如下:
1 #define FUN(a) "a"
2 void main()
3 {
4 cout<<FUN(345)<<endl; //a
5 cout<<FUN(a)<<endl; //a
6 cout<<FUN("a")<<endl; //a
7 char *str=FUN(abc);
8 cout<<str<<endl; //a
9 }
? ? ? ?通過上例可以看到,如果這樣寫,不論實參是什么,都不會擺脫被替換為“a”的命運。也許,你會問,那么我要實現FUN(345)被替換為“345”??腫么辦呢??
? ? ? ?請看下面這個用法
?【9】有參宏定義中#的有何作用?
? ? ? ? ?示例代碼如下:
1 #define STR(str) #str
2
3 void main()
4 {
5 cout<<STR(abc)<<endl; //abc
6 cout<<STR("abc")<<endl; //"abc"
7 cout<<STR(123)<<endl; //123
8 cout<<STR(my#name)<<endl; //my#name
9 // cout<<STR(()<<endl; //error!!編譯錯誤
10 cout<<STR(.)<<endl; //.
11 // cout<<STR(A,B)<<endl; //error!!編譯錯誤
12 cout<<STR(())<<endl; //()
13 const char * str=STR(liuyong);
14 cout<<str<<endl; //liuyong
15 }
? ? ? ??備注:代碼編譯環境為VS2010 ?那么相信“#”的作用也一目了然。在此不作贅述。
? 【10】有參宏定義中##有何作用?
? ? ? ? ? 示例代碼如下:
1 #define SIGN( x ) INT_##x
2 #define WIDE(str) L##str
3
4 void main()
5 {
6 int SIGN(a);
7 // int INT_a; //error!! redefinition
8 char * WIDE(a);
9 // char *La; //error!! redefinition
10 }
? 【11】當一個宏自己調用自己時,會發生什么呢?
? ? ? ? ?例如:#define ?TEST(x) ? ( x + TEST( x ) )
? ? ? ? ?TEST(1); 會發生什么呢?為了防止無限制遞歸展開,語法規定:當一個宏遇到自己時,就停止展開。
? ? ? ? ?也就是說,當對TEST(1)進行展開時,展開過程中又發現了一個TEST,那么就將這個TEST當作一個
? ? ? ? ?一般的符號。TEST(1)最終被展開為:1 +?TEST(1)。
? 【12】可以舉一個變參宏的例子嗎?
? ? ? ? ?示例代碼如下:
1 #define LOG( format,... ) printf( format, __VA_ARGS__ )
2
3 void main()
4 {
5 int a = 10;
6 char *str = "abc";
7 LOG("%d,%s",a,str); //10,abc
8 }
? 【13】當宏作為參數被放進另一個宏體時,將會發生什么?
? ? ? ? ? ??當一個宏參數被放進宏體時,這個宏參數會首先被全部展開(當然,沒有絕對,也有例外)。當展開后的宏參數被放進宏體時,
? ? ? ? ?預處理器對新展開的宏體進行第二次掃描。并繼續展開。舉例說明:
? ? ? ? ?示例代碼如下:
1 #define PARAM(x) x
2 #define ADDPARAM(x) INT_##x
3
4 void main()
5 {
6 int PARAM(ADDPARAM(1));
7 // int INT_1; //error!! 編譯錯誤 重復定義
8 }
? ? ? ? ?因為ADDPARAM(1)是作為PARAM的宏參數,所以先將ADDPARAM(1)展開為INT_1,然后再將INT_1放進PARAM。
? ? ? ? ?也有例外,如果PARAM宏內對宏參數使用了#?或者 ## ,那么宏參數不再被展開。例如:
? ? ? ? ?#define PARAM( x ) #x
? ? ? ? ?#define ADDPARAM( x ) INT_##x
? ? ? ? ?PARAM( ADDPARAM( 1 ) ); 將被展開為"ADDPARAM( 1 )"。
?
Good Good Study, Day Day Up.
順序 選擇 循環 總結