3

Why this code give to me value "4" instead of "0"?

#define PLUGIN_PPQ 96
#define MIDIENGINE_SCORE_LENGTH PLUGIN_PPQ * 4

int main ()
{
    int mCurrentPatternPulse = 97;
    int patternBar = (int)floor(mCurrentPatternPulse / MIDIENGINE_SCORE_LENGTH);
    cout << "value: " << patternBar << " (" << MIDIENGINE_SCORE_LENGTH << ")";
}

97/384 (with/without floor) should give to me 0.

But it seems it divides by 96 instead of 384? Even if I print MIDIENGINE_SCORE_LENGTH is 384...

markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 2
    Protip: Use `constexpr` variables instead. They will be processed at compile time like the macro but will respect operator precedence because they are variables, and they are known to the language. – Guillaume Racicot Sep 12 '16 at 13:27
  • @LưuVĩnhPhúc: Other language (C instead of C++). Root cause is shared, solution isn't. C doesn't have `constexpr`. – MSalters Sep 12 '16 at 14:19
  • @MSalters I don't get you. That link explains the OP's problem. You can find many C++ questions are reported as duplicated by that question like [this one](http://stackoverflow.com/q/35039313/995714). `constexpr` is a suggestion, not an answer to this question – phuclv Sep 12 '16 at 15:10

3 Answers3

6

If you unpick the macro, then you get

floor(mCurrentPatternPulse / PLUGIN_PPQ * 4);

Since / and * have the same precedence, evaluation is from left to right, so the expression is equivalent to

floor((mCurrentPatternPulse / PLUGIN_PPQ) * 4)

Note that (mCurrentPatternPulse / PLUGIN_PPQ) is performed in integer arithmetic, so any remainder is discarded prior to the multiplication.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
5

#defines are just text substitution. You need to look up operator precedence.

Anon Mail
  • 4,660
  • 1
  • 18
  • 21
5

Imagine it being a "string-replace" and not a math operation.

So MIDIENGINE_SCORE_LENGTHis not 384 but 96 *4

so your code looks like:

floor(mCurrentPatternPulse / 96 *4 );

and the mCurrentPatternPulse / 96 will be evaluated first.

Just add some brackets:

floor(mCurrentPatternPulse / ( MIDIENGINE_SCORE_LENGTH ) );

Edit:

Or even better put them in the define directly:

#define MIDIENGINE_SCORE_LENGTH ( PLUGIN_PPQ * 4 )
Hayt
  • 5,210
  • 30
  • 37