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
  • 45,272
  • 113
  • 282
  • 475
  • 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
  • 227,678
  • 33
  • 352
  • 470
5

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

Anon Mail
  • 4,575
  • 1
  • 17
  • 20
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,001
  • 26
  • 34