views:

352

answers:

4

I just wrote the following line of code:

if (++(data_ptr->count) > threshold) { /*...*/ } // example 1

My intent is to increment the count variable within the data structure that data_ptr points to before making the comparison to threshold, and this line of code works.

If I had instead wanted to increment data_ptr before making the comparison, I would have written this:

if ((++data_ptr)->count > threshold) { /*...*/ } // example 2

Out of curiosity, I also tried this line of code:

if (++data_ptr->count > threshold) { /*...*/ } // example 3

And found that it behaves exactly the same as the first one.

First question: Why does example #3 work the same as example #1? Is it a matter of operator precendence? Something in the standard? I had to write a quick test program becuase the answer was not obvious to me.

Second question: Should I write this if statement differently? I could perform the increment first, on its own line, and then test the condition in order to avoid any possible confusion. Is this necessary, or are the first two examples obvious enough on their own?

+3  A: 
  1. The -> operator binds tighter than ++.
  2. They're both well-defined and I think they're easy to read. Things would only get dodgy if you had additional references to data_ptr in the same expression.
ak
+4  A: 

Yes, this is a question of operator precedence. The arrow operator has higher precedence than the increment operator.

To answer your second question, I would generally separate this type of construct out into two separate statements:

++(data_ptr->count);
if(data_ptr->count > threshold) { /*...*/ }

This emphasizes what is going on and eliminates possible confusion. However, this is probably a question of preference.

Martin B
+7  A: 

1) Precedence

2) Preference

anon
+1 Succinct. ``
e.James
+5  A: 
  1. Operator precedence dictates the behaviour you observed.
  2. It wouldn't hurt much if you separated the increment from the comparison in this example, but sometimes you want to have a condition with increment in the middle of a sequence of conditions, and then trying to separate the increment from the test can hurt the readability of the code by introducing nesting that would otherwise be unnecessary.

For example:

if (...1...)
    ...2...
else if (++data_ptr->count > threshold)
    ...3...
else
    ...4...

Versus:

if (...1...)
    ...2...
else
{
    ++data_ptr->count;
    if (data_ptr->count > threshold)
        ...3...
    else
        ...4...
}
Jonathan Leffler