今天花了點時間把第六章看了。
1.不能忽視巨集定義中的空格。
與巨集呼叫相比,巨集定義顯得「暗藏機關」。例如下列**:
#define f (x) ( (x) - 1 )
答案有兩種:
1.f(x) 代表( (x) - 1 )
2.f 代表(x) ( (x) - 1 )
正確答案是第二種,因為f與(x)之間多了乙個空格!這一規則不適用於巨集呼叫,只適用
於巨集定義,也就是說,f(3)與f (3)的結果是一樣的。
2.巨集並不是函式
因為巨集從表面上看上去其行為與函式很相似,所以程式設計師有時會情不自禁的把兩者視為
等同。例如下列**:
#define abs(x) ( (x) > 0 ? (x) : -(x) )
如果以abs(a-b)的形式呼叫並且引數沒有被括號括起來就會發現問題了,因此為了避免出現
這類問題,需要將引數和結果都括起來。
在巨集定義中,如果乙個引數被多次用到,那麼這個引數將會被多次求值,因此,以下代
碼會出現問題(部分**):
#define max(a,b) ( (a) > (b) ? (a) : (b) )
biggest = x[0];
i = 1;
while ( i < n )
biggest = max( biggest, x[ i++ ]);
以上的**不僅效率低下,而且還會出錯。展開後會發現x[ i++ ]會被求值兩次,從而導
致錯誤。如果max是函式則不會有這些問題。為了解決這類問題,我們需要確保巨集定義中
的引數沒有***,因此我們需要將while迴圈改為for迴圈。或者使用函式或**。
使用巨集的另乙個危險就是巨集展開後可能產生非常龐大的表示式,占用空間遠遠超出了編
程者所預期的空間。同樣是max的巨集定義,如果對四個數進行比較max( a,max( b,max(c,d) ) );,
你會發現展開的**是在太長了!
3.巨集不是語句
有時,程式設計者會試圖定義巨集的行為與語句類似,但這樣做會發現結果令人驚訝。
#define a(x) if(!x) assert_error(_file_,_line_)
if ( x>0 && y>0)
a(x>y);
else
a(y>x);
_file_和_line_是內建的。展開並整理**後你會發現這是「懸垂」問題,有人就會說,那
我們在巨集定義是加上括號,把句子括起來,那麼你會發現另乙個問題,else前面會多出乙個
分號,這是乙個語法錯誤。但是如果去掉**中的分號你就會發現這**會有一些「怪異」。
4.巨集不是型別定義
巨集的另乙個用途是使多個不同變數的型別可以在乙個地方宣告,相當於型別定義。如:
#define t int
t a;
t b,c;
這樣子的做法有乙個優點——可移植性。但是最好還是使用型別定義,因為這種做法也
是會出現問題的。
#define t1 int *
typedef int * t2;
t1 a,b;
t2 c,d;
第乙個宣告展開後你會發現,a被宣告為了指標,而b則是乙個整型變數;而第二個聲
明則是宣告兩個指標變數。
這是第六章。
第六章 預處理器
巨集就是文字展開,實際中可以展開寫出來發現錯誤。6.1 不能忽視巨集定義中的空格 6.2 巨集並不是函式 巨集定義乙個函式時,1 要把每個引數用括號括起來 2 同時也要把整個表示式括起來。3 要確保巨集中的引數沒有 define max a,b a b a b max big,x i 這時 有可能被...
第六章預處理
在程式設計中,為了方便,有的時候我們會使用巨集定義,首先,我們要明確一點,巨集定義與函式式不同的,巨集定義的功能就是替換,在編譯時替換掉 裡面的使用巨集的地方。如求兩個數中大的乙個 define max x,y x y x y 在使用巨集定義時間,我們要注意幾點 1.定義時中間不能有空格,如 def...
mysql第六章 第六章 mysql日誌
第六章 mysql日誌 一 錯誤日誌 錯誤日誌的預設存放路徑是 mysql 存放資料的地方 hostname.err 1.修改錯誤日誌存放路徑 mysqld log error data mysql mysql.log 2.檢視配置命令 show variables like log error 3...