如何理解这个C宏?

如何理解这个C宏?,c,c-preprocessor,C,C Preprocessor,我无法理解此代码 #define sqt(x) x*x int main(){ print("%d",sqt(3+1)); } 我手动得到10的输出。但是当编写代码并编译它时,我得到的答案是7。请对此进行解释。记住,因为您使用的是宏,3+1在调用sqt之前不会进行计算x变为3+1(不是4),则运算顺序导致产生意外的答案,因为加法发生在乘法之后 换句话说: sqt(3 + 1) 扩展到: 3 + 1 * 3 + 1 然后,当你像计算其他方程一样计算它时: 3 + 1 * 3 + 1 // M

我无法理解此代码

#define sqt(x) x*x
int main(){
print("%d",sqt(3+1));
}

我手动得到10的输出。但是当编写代码并编译它时,我得到的答案是7。请对此进行解释。

记住,因为您使用的是宏,
3+1
在调用
sqt
之前不会进行计算
x
变为
3+1
(不是
4
),则运算顺序导致产生意外的答案,因为加法发生在乘法之后

换句话说:

sqt(3 + 1)
扩展到:

3 + 1 * 3 + 1
然后,当你像计算其他方程一样计算它时:

3 + 1 * 3 + 1 // Multiplication happens first
= 3 + 3 + 1
= 7
这是一个很好的例子,说明了为什么不应该使用宏,除非它们是严格必需的,或者您已经采取了适当的措施来确保不会发生操作顺序错误之类的事情。正如@Barmar指出的,可以通过将宏展开以包含显式括号来纠正这种特殊情况:

#define sqt(x) ((x)*(x))
这将导致评估结果不同,并给出正确答案:

(3 + 1) * (3 + 1)
4 * 4
16

请记住,由于您使用的是宏,
3+1
在调用
sqt
之前不会进行计算
x
变为
3+1
(不是
4
),则运算顺序导致产生意外的答案,因为加法发生在乘法之后

换句话说:

sqt(3 + 1)
扩展到:

3 + 1 * 3 + 1
然后,当你像计算其他方程一样计算它时:

3 + 1 * 3 + 1 // Multiplication happens first
= 3 + 3 + 1
= 7
这是一个很好的例子,说明了为什么不应该使用宏,除非它们是严格必需的,或者您已经采取了适当的措施来确保不会发生操作顺序错误之类的事情。正如@Barmar指出的,可以通过将宏展开以包含显式括号来纠正这种特殊情况:

#define sqt(x) ((x)*(x))
这将导致评估结果不同,并给出正确答案:

(3 + 1) * (3 + 1)
4 * 4
16


你是怎么得到10的?7是正确答案。如果用户希望答案为16,请添加一些括号。我不知道怎么到10。@kingW3也许他的意思是
0x10
?:)@LeednielCrocker或者他可能认为出于某种原因它会扩展到
3*3+1
。你是怎么得到10的?7是正确答案。如果用户希望答案为16,请添加一些括号。我不知道怎么到10。@kingW3也许他的意思是
0x10
?:)@LeeDanielCrocker或者他可能认为出于某种原因它将扩展到
3*3+1
。您应该演示如何修复宏,使其按预期工作。像这样的宏非常好,没有理由不使用它们——只要你包含括号。@LeedianelCrocker使用这样的宏的唯一原因是因为你使用的是一个有30年历史的编译器,它不会通过内联扩展来优化小函数。虽然它们不是真的必要,但它们并不少见,但这样的错误也不会发生。@user3386109你抓到我了。像这样的宏真的是一个PITA。你应该展示如何修复宏,使其按预期工作。像这样的宏非常好,没有理由不使用它们——只要你包含括号。@LeedianelCrocker使用这样的宏的唯一原因是因为你使用的是一个有30年历史的编译器,它不会通过内联扩展来优化小函数。虽然它们不是真的必要,但它们并不少见,但这样的错误也不会发生。@user3386109你抓到我了。像这样的宏实际上是一个PITA。