-2

writing leetcode I use the macro like this:

#define max(a,b) ((a) > (b))?(a):(b)

it is wrong,when i change the macro like this,it's right

#define max(a,b) (((a) > (b))?(a):(b))

can't figure out why does this different.Here is the code,you can check it out.

#define UNBALANCED 99

#define max(a,b) (((a) > (b))?(a):(b))
int getHeight(struct TreeNode * root)
{
    if(NULL == root)
        return -1;
    int l = getHeight(root->left);
    int r = getHeight(root->right);
    if(UNBALANCED == l || UNBALANCED == r || abs(l-r) > 1)
        return UNBALANCED;

    return 1 + max(l,r);

}
bool isBalanced(struct TreeNode* root) 
{
    if(NULL == root)
        return true;

    return getHeight(root) != UNBALANCED;



}

that is different with The need for parentheses in macros in C

52coder
  • 179
  • 1
  • 2
  • 11
  • What's the context in which the first one gets you the wrong result? – Charles Srstka Mar 25 '18 at 02:28
  • The answer depend on the context in which you use the macros. Please add an example of your code where you use them. – DYZ Mar 25 '18 at 02:28
  • The simple rule is: always surround a function-like macro with an outer set of parens so that operator precedence doesn't interact unexpectedly with it. – Michael Burr Mar 25 '18 at 06:53
  • Possible duplicate of [The need for parentheses in macros in C](https://stackoverflow.com/questions/10820340/the-need-for-parentheses-in-macros-in-c) – Martin James Mar 25 '18 at 07:09
  • This situation may be different in a very strict way than the suggested duplicate (which is about the need to use parens around the macro parameters), but the same rationale applies to the macro as a whole. Just put parens around the whole macro expression. The only times you should not have them is when you really know why and can explain that reason to someone else. – Michael Burr Mar 25 '18 at 18:14

3 Answers3

1

The former fails to isolate the macro replacement from neighboring operands. For example:

1 + max(a, b)

expands to:

1 + ((a) > (b))?(a):(b)

and that groups as:

(1 + ((a) > (b))) ? (a) : (b)

Then (1 + ((a) > (b))) is always nonzero, so (a) is always chosen.

To prevent this, a macro that expands to an expression should use parenthesis around its entire expression to prevent its parts from grouping with neighboring operands.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • I modify the question, in that recursive function,you think it's make a difference? – 52coder Mar 25 '18 at 06:42
  • you comment is an example explain the former was wrong,in my case,I just return 1+max(l,r), can not think a reason,why it's different. thanks for your answer – 52coder Mar 25 '18 at 06:46
  • @52coder: The problem is the same with an operand on the left. I have changed the example to show how it applies in your code. – Eric Postpischil Mar 25 '18 at 10:40
  • thanks, i think i got what you say, + is prior than ?:,when cal from the right as you say it's equal to (1 + ((a) > (b))) ? (a) : (b),thanks a lot! – 52coder Mar 25 '18 at 14:37
0

The second version of your macro has extra parentheses which make the expression ((a) > (b))?(a):(b) evaluated as a whole. More code would be needed to explain exactly why the first one is wrong in your case. Also, see this.

BobMorane
  • 3,870
  • 3
  • 20
  • 42
0

Arguably both of them are incorrect; what if you wanted to use your macro like:

MAX(i++, j++)

The resulting ternary-operator expression from your examples cause whichever expression is smaller to be evaluated twice. Yowch! Since you (and most future readers) likely use GCC or clang, here's a better example with some compiler extensions (__typeof__ and statement expressions) that both of them support.

#define MAX(a, b) ({ __typeof__ (a) a__ = (a); \
                     __typeof__ (b) b__ = (b); \
                     (a__ > b__) ? a__ : b__; })
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • I think it is different,your example here use i++ and j++,but my example above just use a and b instead of a++ b++,why it's different? – 52coder Mar 25 '18 at 03:01
  • Your first example is wrong because you don't fully parenthesize your expression, so it is subject to order-of-operations effects at its use site. Other comments and answers have made that clear. I just wanted to add that there is an additional problem you may not have considered when writing your macros. – Carl Norum Mar 25 '18 at 03:02
  • using gcc ,how can i know what the compiler explain to the macro i write? – 52coder Mar 25 '18 at 03:03