为什么宏值为0而不是1?

时间:2011-11-02 13:39:26

标签: c macros

此处base->leftNULLbase->right->height0

((((base->left ? base->left->height : -1)) > ((base->right ? base->right->height : -1))) 
? 
((base->left ? base->left->height : -1) + 1) 
: 
((base->right ? base->right->height : -1) + 1))

IMO上述表达式的结果应为1

但是当我将其打印出来时,结果却是0

任何人都知道原因吗?

这是gcc 4.3.2的错误吗?

更新

表达式是怎么来的?

#define MAX_PLUS_1(a, b) (((a) > (b)) ? (a + 1) : (b + 1))
#define BINARY_TREE_HEIGHT(node) (node ? node->height : -1)
#define BINARY_TREE_SYN_HEIGHT(left, right) \
    MAX_PLUS_1(\
        BINARY_TREE_HEIGHT(left),\
        BINARY_TREE_HEIGHT(right)\
    )

真的是BINARY_TREE_SYN_HEIGHT(base->left, base->right)

如果我用函数替换MAX_PLUS_1,问题就消失了:

int MAX_PLUS_1(int a, int b){
    return (((a) > (b)) ? (a + 1) : (b + 1));
}

3 个答案:

答案 0 :(得分:2)

您的代码设计糟糕。它作为一个函数运行的事实,让我怀疑这来自对宏参数的多重评估。

  • 永远不会有两次评估其参数的宏。如果论证有副作用你就搞砸了
  • 总是在您的宏参数周围加上括号。根据调用时的参数,运算符优先级可能会给你一些与你想象的完全不同的东西
  • 只要有可能,只需使用inline函数而不是宏。这是有效的,具有类型检查并保证参数仅被评估一次。
  • 在您的特定情况下,根本没有理由在宏中包含+1。将其置于宏或函数调用之外。
  • 您似乎无法控制您正在使用的类型。您说您的height字段是无符号类型,但是您为我们提供了一个具有int参数的函数调用。
  • 编辑:通常uint32_t不适合作为应用程序类型。为什么32位为什么不是64? “尺寸”,“长度”等类似的最佳标准无符号类型通常为size_t。让系统决定它处理的最佳类型。

答案 1 :(得分:1)

根据评论讨论中的其他信息,您的height字段未签名。这意味着当你尝试将它与-1进行比较时,你最终会遇到麻烦 - (uint32_t)-1 == 0xFFFF_FFFF =非常大的数字,所以当你不这样做的时候,'left'分支会在某个时候选择'right'分支。期待它。

MAX_PLUS_1()写为函数可以解决或隐藏这个问题,因为您使用int作为参数。这意味着在height值和(int)-1之间进行了比较,这是您想要的。

答案 2 :(得分:0)

问题是你的变量不是你认为的那样。

如果用值替换那些来测试三元组,它确实会打印1

((((0 ? 1 : -1)) > ((1 ? 0 : -1))) 
?
((0 ? 0 : -1) + 1)
:        
((1 ? 0 : -1) + 1));