在宏定義當中,常常可以看到宏的參數以及整個宏的定義都被小括號包圍,就像下面的 MIN、MAX、ABS 宏一樣:
上面的圖截取自 iOS 的系統庫,那為什么它們需要這些括號包圍起來呢?
下面假如我們自定義了宏 ceil_div,代碼如下:
#define ceil_div(x, y) (x + y - 1) / y
這個宏的本意是將 x 除以 y,然后將得到的結果向上取整。比如 x = 4,y = 3,那么 ceil_div(4, 3) 的值就是2。如果參數僅僅是這些數字,使用起來沒有什么問題,cei_div(4, 3) 經過宏擴展之后成為:
(4 + 3 - 1) / 3
這個符合預期。但是假如參數變得復雜,包含了一些運算符,比如 ceil_div(b & c, sizeof(int)),講過宏擴展成為下面的樣子:
(b & c + sizeof(int) -1 ) / sizeof(int)
由於 & 的優先級比算數運算符 + 的優先級低,那么實際上的運算過程是下面這樣的:
(b & (c + sizeof(int)) -1 ) / sizeof(int)
而期望的運算結果是先進行 & 運算,后進行 + 運算:
((b & c) + sizeof(int) -1 ) / sizeof(int)
所以,如果對於宏參數 x、y 不加括號,顯然在涉及操作符優先級的情況下,會出現錯誤。那現在對此進行修正,將宏 ceil_div 的參數用括號進行包圍:
#define ceil_div(x, y) ((x) + (y) - 1) / (y)
使用這個定義,就能得到上面期望的結果。但是僅僅只是對宏參數加括號,仍然在一些情況下會有問題,比如像下面使用宏 ceil_div:
sizeof ceil_div(1, 2)
宏被擴展之后,會成為下面的情形:
sizeof ((1) + (2) - 1) / (2)
由於 sizeof 的優先級比算術運算符 / 的優先級高,因此實際上是先進行 sizeof 的運算,再進行除法運算,即:
sizeof (((1) + (2) - 1)) / (2)
而期望的結果是先求宏的值,然后再進行 sizeof 運算:
sizeof (((1) + (2) - 1) / (2))
想要得到正確結果的修改也很簡單,直接將整個宏定義使用括號包圍即可:
#define ceil_div(x, y) (((x) + (y) - 1) / (y))
因此,宏的參數以及宏定義加括號,是為了解決操作符優先級的問題。