TomZz 发表于 2022-7-3 16:41:18

关于宏定义带运算的逻辑

s1e5的作业问题:
#define F(n) 2*n
F(3+2)的结果是2*3+2
按着这个逻辑去理解,当宏定义改为
#define F(n) pow(2,n)
F(3+2)结果应该是 2的3次方+2=10。但是其实际结果是 32 即 2的五次方

临时号 发表于 2022-7-3 16:41:19

TomZz 发表于 2022-7-3 16:54
那为什么F(n) pow(2,n)可以先运算括号里面的,而F(n)2*n就不可以呢?
小甲鱼的解释是3+2不会进行相关 ...

宏定义预处理指令,即在程序还没编译前进行预处理
所以这里只会进行替换操作,不会进行任何的运算和程序的执行
按你上面的例子
#define F(n) 2*n
它只会原封不动的替换,那么F(3+2)就会替换成2*3+2,他会将你括号里的当成n,原封不动的替换到n的位置
至于加不加括号,那不是编译器这个阶段管的事,尽管2*3+2在后续计算时会先算2*3
#define F(n) pow(2,n)
它在这里也只会原封不动的替换,替换成pow(2,3+2),那在后续计算中按照规定及就会先算函数参数里的表达式,即3+2=5,这样就变成了pow(2,5)

风车呼呼呼 发表于 2022-7-3 16:45:02

F(3+2) -> pow(2, 3+2) -> pow(2, 5)=2的5次方
2的3次方+2 是 pow(2, 3) + 2

TomZz 发表于 2022-7-3 16:54:02

风车呼呼呼 发表于 2022-7-3 16:45
F(3+2) -> pow(2, 3+2) -> pow(2, 5)=2的5次方
2的3次方+2 是 pow(2, 3) + 2

那为什么F(n) pow(2,n)可以先运算括号里面的,而F(n)2*n就不可以呢?
小甲鱼的解释是3+2不会进行相关运算
“F(3+2) == 2*3+2 == 8,注意,宏定义是在程序编译时先进行的预处理,做法是直接将标识符替换为常量,并不会进行相关运算。因此,直接将 F(3+2) 替换为 2*3+2”

风车呼呼呼 发表于 2022-7-3 17:26:03

TomZz 发表于 2022-7-3 16:54
那为什么F(n) pow(2,n)可以先运算括号里面的,而F(n)2*n就不可以呢?
小甲鱼的解释是3+2不会进行相关 ...

宏定义就是文本替换,本来就不会做任何运算。
替换完之后该怎么算就怎么算。pow(2,n)替换完 为 pow(2,3+2)。
前面那个F(3+2)替换完是 2*3+2,计算出来是8有什么问题。
如果想要表达2倍的n,那应该定义为 #define F(n)2 * (n),这样预处理之后就是,2*(3+2)=10

ExiaGN001 发表于 2022-7-3 21:18:18

所有n加括号(n)

TomZz 发表于 2022-7-3 21:39:50

ExiaGN001 发表于 2022-7-3 21:18
所有n加括号(n)

是的,这样就可以确保类函数的运算方式了。而不会产生一些奇怪的问题。

ExiaGN001 发表于 2022-7-3 21:41:26

TomZz 发表于 2022-7-3 21:39
是的,这样就可以确保类函数的运算方式了。而不会产生一些奇怪的问题。

确实。
您还有什么困惑的话,我愿意随时解答。
页: [1]
查看完整版本: 关于宏定义带运算的逻辑