C++ 如何评价这一说法?

C++ 如何评价这一说法?,c++,C++,如果我将一个数字的绝对值定义为 #define ABS(X) X >= 0 ? X : (-1) * X 你会怎么做 ABS(2) + ABS(-3) 评估到?我的朋友声称它的计算结果为2。预处理器执行基于文本(实际上是基于令牌)的替换。它不注意逻辑表达式分组 给定 扩展到 2 >= 0 ? 2 : (-1) * 2 -3 >= 0 ? -3 : (-1) * -3 2 >= 0 ? 2 : (-1) * 2 + -3 >= 0 ? -3 : (-1) *

如果我将一个数字的绝对值定义为

#define ABS(X) X >= 0 ? X : (-1) * X
你会怎么做

ABS(2) + ABS(-3)

评估到?我的朋友声称它的计算结果为2。

预处理器执行基于文本(实际上是基于令牌)的替换。它不注意逻辑表达式分组

给定

扩展到

2 >= 0 ? 2 : (-1) * 2
-3 >= 0 ? -3 : (-1) * -3
2 >= 0 ? 2 : (-1) * 2 + -3 >= 0 ? -3 : (-1) * -3

扩展到

2 >= 0 ? 2 : (-1) * 2
-3 >= 0 ? -3 : (-1) * -3
2 >= 0 ? 2 : (-1) * 2 + -3 >= 0 ? -3 : (-1) * -3
所以

扩展到

2 >= 0 ? 2 : (-1) * 2
-3 >= 0 ? -3 : (-1) * -3
2 >= 0 ? 2 : (-1) * 2 + -3 >= 0 ? -3 : (-1) * -3
现在看看运算符是如何分组的,您将看到为什么5的直观答案不正确。

当您键入:

ABS(2) + ABS(-3)
这将取代:

2 >= 0 ? 2 : (-1) * 2 + -3 >= 0 ? -3 : (-1) * -3
您可以将其分解为:

2 >= 0 ? 2 : -5 >= 0 ? -3 : (-1) * -3
或:

第一部分(
2>=0
)计算结果为true,因此计算结果为
2

请注意,您可以通过将宏编写为以下代码来轻松解决此问题:

#define ABS(X) ((X) >= 0 ? (X) : (-1) * (X))
这将按预期保持评估顺序,并使其解析为5而不是2。也就是说,使用内联函数会更简洁,避免整个场景。

以下是我的理解:

ABS(2) + ABS(-3)
变成:

2 >= 0 ? 2 : (-1) * 2 + -3 >= 0 ? -3 : (-1) * -3
添加一些用于澄清的参数:

(2 >= 0) ? 2 : (((-1) * 2 + -3 >= 0) ? -3 : (-1) * -3)
和评估:
2实际上>=0,因此:2
(以及以
开头的所有其他内容((-1
)将被忽略)


所以,我同意你朋友的看法。

为什么不试试看呢?我也想知道为什么。演示一下为什么不应该使用#定义宏-使用内联函数instead@aschepler需要更多参数:
#定义ABS(X)((X)>=0?(X):(-1)*(X))
(对于
ABS(i+1)
)@michaelb958:说得好;这是与此相对应的规则,它们应该一起学习和记住。这是C预处理器;你不能假设没有paren。CPP执行纯文本替换。我对paren没有任何假设。我按照正常的操作顺序放置它们,只是为了帮助人们理解如果我把它们放在适当的位置,它们根本不会改变计算机的解释。这会教我盲目地误读东西……我只是假设你是在仓促地使用,然后重新计算,以强迫5的“正确”结果。对不起,你对宏的修复,把它包裹在括弧里,对所有的情况都不起作用。考虑<代码> ABS(t>=0?- 1:1)。。这不会像人类预期的那样扩展。对于宏,通常将参数包装在参数中,然后包装整个宏:
#定义ABS(X)((X)>=0?(X):(-1)*(X))
(即使这样也不能处理所有情况,尤其是X有副作用的情况。但它做得相当好)@abelenky True-将内部
X
封装在括号中,以尝试在我的答案中处理此问题。这一点很好。