产生错误数字的宏
macro producing wrong number
我不明白为什么下面的代码打印 2 而不是 1...
#include <stdio.h>
#define ABS(x) ((x) < 0) ? -(x) : (x)
int main()
{
printf("%d", ABS(ABS(-2)-(ABS(-3))));
return 0;
}
这个问题出现在我们的考试中,我回答的输出是 1,但编译后我得到 2...谁能解释一下表达式的实际作用...提前致谢。
括号有问题。如果展开宏,您将得到一个复杂的嵌套三元运算,其计算结果为 2
(请参阅更新中的展开)。为了获得理想的结果,用括号将宏括起来。
更新:手动扩容:
ABS(ABS(-2)-(ABS(-3)))
扩展为:
((ABS(-2)-(ABS(-3))) < 0) ? -(ABS(-2)-(ABS(-3))) : (ABS(-2)-(ABS(-3)))
ABS(-3)
到处都是括号,所以它被安全地评估为 3
,所以不需要扩展它。所以我们最终得到:
(( ((-2) < 0) ? -(-2) : (-2) - 3) < 0) ? -(ABS(-2)-3) : (ABS(-2)-3)
(ABS(-2)-3)
将扩展为
((-2) < 0) ? -(-2) : (-2) - 3 = 2
整体评价:
(( true ? 2 : -5 < 0) ? -2 : 2
或
(2 < 0) ? -2 : 2 = 2
并且是观察到的结果,希望有借鉴意义
这是eno
你忘记了外括号,试试这个:
#define ABS(x) (((x) < 0) ? -(x) : (x))
#include <stdio.h>
#define ABS(x) ((x) < 0) ? -(x) : (x))
int main()
{
printf( "%d", ABS( ABS(-2) - ABS(-3) ) );
return 0;
}
您忘记了 #define
中的右括号 )
。
另外,return
需要小写
我放了空格,这样你可以更清楚地看到分组。
在 http://coliru.stacked-crooked.com/a/59700f453a1dcaf9 中使用编译选项 -E
gcc 预处理器已解决此问题:
printf("%d\n", ABS(ABS(-2)-(ABS(-3))));
对此:
printf("%d\n", ((((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) < 0) ? -(((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) : (((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))));
自己检查一下
您需要在 ABS
定义的表达式周围加上括号。而不是
#define ABS(x) ((x) < 0) ? -(x) : (x)
你需要:
#define ABS(x) (((x) < 0) ? -(x) : (x))
^----------------------^
没有它,表达式 ABS(ABS(-2)-(ABS(-3)))
扩展为:
((((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) < 0) ? -(((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) : (((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3)))
这将是一项艰难的分析,以了解哪里出了问题。但是,如果您查看表达式的开头,您会发现第一项与第二项相吻合。
((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ...
^^ (-2) Runs into the next term
表达式的值很难预测。如果在宏定义的表达式周围添加括号,您将看到:
( (((-2) < 0) ? -(-2) : (-2)) - ( (((-3) < 0) ...
^ ------ one term ------- ^ There is no running in to the next term.
让我们手动展开该宏:
ABS(-3) == ((-3) < 0) ? -(-3) : (-3)
ABS(-2) == ((-2) < 0) ? -(-2) : (-2)
ABS(-2) - ABS(-3) ==
((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)
现在我们遇到了一个问题:二进制 -
的优先级高于 ?:
,因此上面的内容被 解析 为:
((-2) < 0) ? -(-2) :
((-2) - ((-3) < 0) ? -(-3) : (-3))
由于 (-2) < 0
为真,我们评估 -(-2)
。那么:
ABS( ABS(-2) - ABS(-3) ) ==
((((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)) < 0 ?
-(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)) :
(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3))
我们已经确定
((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)
的计算结果为 2
,因此表达式
(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3))
得到评估,你猜怎么着?它的计算结果为 2
.
您需要做的是如下更改您的宏:
ABS(x) ( (x) < 0 ? -(x) : (x) )
然后一切展开为
ABS(-3) == ((-3) < 0 ? -(-3) : (-3))
ABS(-2) == ((-2) < 0 ? -(-2) : (-2))
ABS(-2) - ABS(-3) ==
((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))
ABS(ABS(-2) - ABS(-3)) ==
(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3)) < 0 ?
-(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))) :
((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))
这次,
(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))
计算为 -1
。
剩下的应该从这里清楚了。
正是出于这个原因,您应该始终将表达式宏体包裹在一对外括号中。
我不明白为什么下面的代码打印 2 而不是 1...
#include <stdio.h>
#define ABS(x) ((x) < 0) ? -(x) : (x)
int main()
{
printf("%d", ABS(ABS(-2)-(ABS(-3))));
return 0;
}
这个问题出现在我们的考试中,我回答的输出是 1,但编译后我得到 2...谁能解释一下表达式的实际作用...提前致谢。
括号有问题。如果展开宏,您将得到一个复杂的嵌套三元运算,其计算结果为 2
(请参阅更新中的展开)。为了获得理想的结果,用括号将宏括起来。
更新:手动扩容:
ABS(ABS(-2)-(ABS(-3)))
扩展为:
((ABS(-2)-(ABS(-3))) < 0) ? -(ABS(-2)-(ABS(-3))) : (ABS(-2)-(ABS(-3)))
ABS(-3)
到处都是括号,所以它被安全地评估为 3
,所以不需要扩展它。所以我们最终得到:
(( ((-2) < 0) ? -(-2) : (-2) - 3) < 0) ? -(ABS(-2)-3) : (ABS(-2)-3)
(ABS(-2)-3)
将扩展为
((-2) < 0) ? -(-2) : (-2) - 3 = 2
整体评价:
(( true ? 2 : -5 < 0) ? -2 : 2
或
(2 < 0) ? -2 : 2 = 2
并且是观察到的结果,希望有借鉴意义
这是eno
你忘记了外括号,试试这个:
#define ABS(x) (((x) < 0) ? -(x) : (x))
#include <stdio.h>
#define ABS(x) ((x) < 0) ? -(x) : (x))
int main()
{
printf( "%d", ABS( ABS(-2) - ABS(-3) ) );
return 0;
}
您忘记了 #define
中的右括号 )
。
另外,return
需要小写
我放了空格,这样你可以更清楚地看到分组。
在 http://coliru.stacked-crooked.com/a/59700f453a1dcaf9 中使用编译选项 -E
gcc 预处理器已解决此问题:
printf("%d\n", ABS(ABS(-2)-(ABS(-3))));
对此:
printf("%d\n", ((((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) < 0) ? -(((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) : (((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))));
自己检查一下
您需要在 ABS
定义的表达式周围加上括号。而不是
#define ABS(x) ((x) < 0) ? -(x) : (x)
你需要:
#define ABS(x) (((x) < 0) ? -(x) : (x))
^----------------------^
没有它,表达式 ABS(ABS(-2)-(ABS(-3)))
扩展为:
((((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) < 0) ? -(((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) : (((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3)))
这将是一项艰难的分析,以了解哪里出了问题。但是,如果您查看表达式的开头,您会发现第一项与第二项相吻合。
((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ...
^^ (-2) Runs into the next term
表达式的值很难预测。如果在宏定义的表达式周围添加括号,您将看到:
( (((-2) < 0) ? -(-2) : (-2)) - ( (((-3) < 0) ...
^ ------ one term ------- ^ There is no running in to the next term.
让我们手动展开该宏:
ABS(-3) == ((-3) < 0) ? -(-3) : (-3)
ABS(-2) == ((-2) < 0) ? -(-2) : (-2)
ABS(-2) - ABS(-3) ==
((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)
现在我们遇到了一个问题:二进制 -
的优先级高于 ?:
,因此上面的内容被 解析 为:
((-2) < 0) ? -(-2) :
((-2) - ((-3) < 0) ? -(-3) : (-3))
由于 (-2) < 0
为真,我们评估 -(-2)
。那么:
ABS( ABS(-2) - ABS(-3) ) ==
((((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)) < 0 ?
-(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)) :
(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3))
我们已经确定
((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)
的计算结果为 2
,因此表达式
(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3))
得到评估,你猜怎么着?它的计算结果为 2
.
您需要做的是如下更改您的宏:
ABS(x) ( (x) < 0 ? -(x) : (x) )
然后一切展开为
ABS(-3) == ((-3) < 0 ? -(-3) : (-3))
ABS(-2) == ((-2) < 0 ? -(-2) : (-2))
ABS(-2) - ABS(-3) ==
((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))
ABS(ABS(-2) - ABS(-3)) ==
(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3)) < 0 ?
-(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))) :
((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))
这次,
(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))
计算为 -1
。
剩下的应该从这里清楚了。
正是出于这个原因,您应该始终将表达式宏体包裹在一对外括号中。