0

I am confused about why the following #define macros are not evaluating as expected when used in the following if statement:

#define kOffsetX  2048.0
#define kPositionX (screenSize.width * (kOffsetX/2048.0))-10.0

CGSize screenSize = [CCDirector sharedDirector].winSize;
float potentialPosition = 486.86f;
float playersFieldOffset = 1.0;

if ((potentialPosition - kPositionX) * playersFieldOffset > 0.0) {

Note that kPositionX evaluates to 470.0. The if statement evaluates to FALSE when clearly 486-470 is greater than zero. However, if I put parenthesis around kPositionX, then the if statement properly evaluates to TRUE.

Why is this happening? Is this an improper way to use a #define? If so, what should I be doing?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
JeffB6688
  • 3,782
  • 5
  • 38
  • 58

4 Answers4

4

The preprocessor just replaces all macros by their definition, so

potentialPosition - kPositionX

is expanded to

potentialPosition - (screenSize.width * (2048.0/2048.0))-10.0

which, when evaluated at runtime, gives

486.86 - 480 - 10  = -3.14 < 0

You should always enclose expressions in macros in parentheses:

#define kPositionX ((screenSize.width * (kOffsetX/2048.0))-10.0)

so that the expansion gives

potentialPosition - ((screenSize.width * (2048.0/2048.0))-10.0)

which is what you expect.

This is (one of the) disadvantages of preprocessor macros. Alternatively, you can use for example (inline) functions, see Inline functions vs Preprocessor macros for more information.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
1

Whenever using #define, make sure to wrap the entire contents of the #define in parentheses. This will prevent any incorrect order of operations calculations from happening. So change your #defines to

#define kOffsetX  (2048.0)
#define kPositionX ((screenSize.width * (kOffsetX/2048.0))-10.0)
rekle
  • 2,375
  • 1
  • 18
  • 9
1

#define macros are literal expressions! After any arguments are spliced in (and you aren't using any arguments for this macro), the macro is basically inserted directly into the code. So, while you are expecting

if ((potentialPosition - kPositionX) * playersFieldOffset > 0.0)

to turn into

if ((potentialPosition - (answer of kPositionX) * playersFieldOffset > 0.0)

it actually turns into

if ((potentialPosition - (screenSize.width * (kOffsetX/2048.0)) - 10.0) * playersFieldOffset > 0.0)

Which evaluates incorrectly. You could solve this by either surrounding the whole macro in parentheses.

#define kPositionX ((screenSize.width * (kOffsetX/2048.0)) - 10.0)

or, as you said, surrounding kPositionX with parentheses

if ((potentialPosition - (kPositionX)) * playersFieldOffset > 0.0) {

Also, as a general rule of good practice, macros are usually written in all capitals, with underscores (_) showing a break between words. #define MACRO_NUMBER_ONE

Eliza Wilson
  • 1,031
  • 1
  • 13
  • 38
1

Macros work by string substitution. Your macro kPositionX is of the form (a) - b so when you use it in the subexpression (potentialPosition - kPositionX) the result is:

(potentialPosition - (screenSize.width * (kOffsetX/2048.0)) - 10.0)

in which 10.0 is subtracted from potentialPosition. Probably you wanted:

(potentialPosition - ((screenSize.width * (kOffsetX/2048.0)) - 10.0))

note the extra parentheses - in which 10.0 is added to potentialPosition.

You must always remember that macros use string substitution when defining them, and any macro containing an expression should have outer parentheses to avoid problems:

#define kPositionX ((screenSize.width * (kOffsetX/2048.0)) - 10.0)
CRD
  • 52,522
  • 5
  • 70
  • 86