1
#include <stdio.h>
#define abs(x) (x < 0 ? -x : x)
int x;
int doubleGlobalX()
{
    x*=2;
    return x;
}

int main()
{
    scanf("%d",&x);//5
    printf("%d\n",abs(doubleGlobalX()));//20
    return 0;
}

When the input is 5 the output of this code is 20. When input is 15 the output is 60. Don't know why it doubles the global twice.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 1
    Possible duplicate of [What is double evaluation and why should it be avoided?](https://stackoverflow.com/questions/39439181/what-is-double-evaluation-and-why-should-it-be-avoided) – John Kugelman Oct 19 '19 at 12:12
  • OT: regarding: `scanf("%d",&x);` The `scanf()` family of functions returns the number of successful 'input conversion specifiers' (in this case any returned value other than 1 indicates an error occurred. – user3629249 Oct 20 '19 at 01:07
  • OT: regarding: `#define abs(x) (x < 0 ? -x : x)` Always place parens around the parameter in the result statement to avoid 'text replacement' errors – user3629249 Oct 20 '19 at 01:09

1 Answers1

8
#define abs(x) (x < 0 ? -x : x)

Macros perform textual substitution. Defining an abs() macro like this is a well-known trap because it ends up evaluating x twice. If it were a function it'd be fine, but as a macro it's a problem. abs(doubleGlobalX()) expands to:

doubleGlobalX() < 0 ? -doubleGlobalX() : doubleGlobalX()

It ends up calling doubleGlobalX() twice which causes x to be doubled twice.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Macros substitute preprocessor tokens, not text. These are different; one consequence is that macro replacement cannot form new preprocessor tokens (without the `##` operator), whereas text replacement could. – Eric Postpischil Oct 19 '19 at 12:17
  • 1
    The problem is not the language used. The problem is the statement is false and gives people incorrect information. – Eric Postpischil Oct 19 '19 at 12:36