12

I was just going through certain code which are frequently asked in interviews. I came up with certain questions, if anyone can help me regarding this?

I am totally confused on this now,

#include <stdio.h>
#include <conio.h>

#define square(x) x*x

main()
{
      int i, j;
      i = 4/square(4);
      j = 64/square(4);
      printf("\n %d", i);
      printf("\n %d", j);
      printf("\n %d", square(4));
      getch();
}

The output is:

 4
 64
 16

I am wondering, why did square(4) return 1 when I divided it? I mean, how can I get the value 4 and 64 when I divide it, but when used directly I get 16!!?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nagaraj Tantri
  • 5,172
  • 12
  • 54
  • 78
  • 1
    Just to note that #define square(x) x*x is a clasic C baddy. Try a loop with square(x++); – Jaydee Sep 15 '10 at 15:33
  • 7
    If you really want to confuse yourself and you haven't read any of the answers yet, try replacing `square(4)` everywhere with `square(3+1)`. – JeremyP Sep 15 '10 at 15:40
  • 1
    This was a simple precedence problem. –  Oct 08 '10 at 21:42

11 Answers11

32

square is under-parenthesized: it expands textually, so

#define square(x) x*x
   ...
i=4/square(4);

means

i=4/4*4;

which groups as (4/4) * 4. To fix, add parentheses:

#define square(x) ((x)*(x))

Still a very iffy #define as it evaluates x twice, so square(somefun()) calls the function twice and does not therefore necessarily compute a square but rather the product of the two successive calls, of course;-).

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 4
    +1 for `square(somefun())`. The usual observation in that case is about side effect done twice, but if you imagine `square(rand())` you are getting the product of two random numbers, not the square of a single random number. – RBerteig Sep 15 '10 at 18:42
  • Also consider `square(n++)` which is UB. See also https://stackoverflow.com/a/76719135/480982 – Thomas Weller Jul 19 '23 at 08:19
5

When you write i=4/square(4), the preprocessor expands that to i = 4 / 4 * 4.
Because C groups operations from left to right, the compiler interprets that as i = (4 / 4) * 4, which is equivalent to 1 * 4.

You need to add parentheses, like this:

#define square(x) ((x)*(x))

This way, i=4/square(4) turns into i = 4 / ((4) * (4)).
You need the additional parentheses around x in case you write square(1 + 1), which would otherwise turn into 1 + 1 * 1 + 1, which is evaluated as 1 + (1 * 1) + 1, or 3.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
4
i=4/square(4);

expands to

i=4/4*4; 

which equivalent to

i=(4/4)*4;
Vladimir
  • 170,431
  • 36
  • 387
  • 313
3

Operator precedence is hurting you.

The macro is expanded by the pre-processor such that

  i=4/4*4;
  j=64/4*4;

which is equivalent to:

  i=(4/4)*4;
  j=(64/4)*4;
Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
3

That's because the compiler replaces it with:

i=4/4*4; 
j=64/4*4;

i = (4/4)*4 = 1*4 = 4.

j = (64/4)*4 = 16*4 = 64.

rkellerm
  • 5,362
  • 8
  • 58
  • 95
2

j = 4/square(4) == 4/4*4 == 1*4 == 4

a1ex07
  • 36,826
  • 12
  • 90
  • 103
1

Manually expand the macro in the code, and it will be clear. That is, replace all the square(x) with exactly x*x, in particular don't add any parentheses.

Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79
1

define is just a text macro

main()
{
      int i,j;
      i=4/ 4 * 4;  // 1 * 4
      j=64/4 * 4; // 16 * 4
      printf("\n %d",i);
      printf("\n %d",j);
      printf("\n %d",square(4));
      getch();
}
Tim Hoolihan
  • 12,316
  • 3
  • 41
  • 54
1

It's a macro! So it returns exactly what it substitutes.

i = 4/4*4;   Which is 4...
j = 64/4*4;   Which is 16...

Try this for your macro:

#define square(x) ((x)*(x))
Starkey
  • 9,673
  • 6
  • 31
  • 51
1

Because of operator precedence in the expression after the preprocessor - you'll need to write

#define square(x) (x*x)
Ivo
  • 3,481
  • 1
  • 25
  • 29
1

As the other answers say, you're getting burned by operator precedence. Change your square macro to this:

#define square(x) (x*x)

and it'll work the way you expect.

paleozogt
  • 6,393
  • 11
  • 51
  • 94