0

this program prints out -8 -4 but i wanna know why and why isn't the compiler showing an error about which function to use? why are the results different. i don't know much about defining a function like this can someone explain this too

#include <stdio.h>
#include <stdlib.h>

int foo(int x, int y);

#define foo(x, y) x/y + x

int main() {
    int i = -6, j = 3;
    printf("%d ", foo(i + j, 3));
#undef foo
    printf("%d\n", foo(i + j, 3));
}

int foo(int x, int y) {
    return x/y + x;
}
ndim
  • 35,870
  • 12
  • 47
  • 57
Angela
  • 29
  • 5

4 Answers4

5

If you preprocess the call to the macro foo, you get:

i + j / 3 + i + j

With your values, that's

(-6) + 3 / 3 + (-6) + 3

Which evaluates to -8.

When you undefine the macro foo, you get the function foo instead, where the line return x + y / x is executed.

With i = -6 and j = 3, you get:

(-3) / 3 + -3

Which is -4.

Further reading:

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
3

These two functions are not equivalent due to operator precedence rules.

Remember a #define macro does inline substitution and the arguments themselves are replaced as-is:

#include <stdio.h>
#include <stdlib.h>

int oper_fn(int x, int y) {
    return x/y + x;
}

#define oper_def(x, y) x / y + x

int main() {
    int i = -6, j = 3;
    printf ("oper_fn=%d ",oper_fn( i + j , 3));
    printf ("oper_def=%d\n",oper_def( i + j , 3));
}

What this ends up doing is evaluating:

i + j / 3 + i + j

Due to order of operations, this evaluates as:

i + (j / 3) + i + j

That's not what you want, instead you want:

(i + j) / 3 + (i + j)

Which means you need the macro:

#define oper_def(x, y) ((x) / (y) + (x))

That's how macros are written normally to avoid ambiguity and inconsistency like this.

ndim
  • 35,870
  • 12
  • 47
  • 57
tadman
  • 208,517
  • 23
  • 234
  • 262
  • 2
    In the proper macro definition, wouldn't it make more sense to wrap the whole expression in a pair of parentheses? `#define oper_def(x, y) ((x) / (y) + (x))` Then an expression like `int z = 3*oper_def(7,1) + 4;` will give you the expected result. – ndim Dec 04 '18 at 17:23
  • @ndim That's another important suggestion. – tadman Dec 04 '18 at 17:24
0

Your #define is not at all like the function. It evaluates as

printf ("%d ",i + j / 3 + i + j);

which will naturally generate a different result to the function as the parameters passed the function are evaluated so it sees x as -3 and y as 3.

Chris Turner
  • 8,082
  • 1
  • 14
  • 18
0

when you define

 #define foo(x, y) x / y + x

and then do

 foo( i + j , 3));

you get

 i + j / 3 + i + j

which is

 -6 + 3/ 3 + 3 -6 = -6 + 1 + 3 - 6 = -8

when you call the function foo the i+j is evaluated first

if you want the correct define behavior then do

#define foo(x, y) ((x / y) + x)

You have just discovered why defined functions are a bad idea

pm100
  • 48,078
  • 23
  • 82
  • 145
  • 1
    you should probably put parentheses around the `x`s and `y` as well, since your example will still compile as `((i + j / 3) + i + j)` – absoluteAquarian Dec 04 '18 at 17:21
  • 2
    Normally the `x` and `y` should each by individually parenthesized in the macro definition; i.e., `#define foo(x, y) ((x) / (y) + (x))` to handle the case where the macro argument is itself an expression. – TypeIA Dec 04 '18 at 17:21