1

宏定义里面为什么要加括号? - chaoguo1234

 2 years ago
source link: https://www.cnblogs.com/chaoguo1234/p/16026249.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

宏定义里面为什么要加括号?

在宏定义当中,常常可以看到宏的参数以及整个宏的定义都被小括号包围,就像下面的 MIN、MAX、ABS 宏一样:

489427-20220319132139764-644556486.png

上面的图截取自 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))

因此,宏的参数以及宏定义加括号,是为了解决操作符优先级的问题。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK