第六章 預處理器

2021-09-30 05:48:50 字數 1836 閱讀 1082

今天花了點時間把第六章看了。

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...