1

Why am I getting the answer "odd" instead of "even"?

#include<stdio.h>
#define ODD(x) x%2?0:1
int main()
{
    int a=5;

    if(ODD(a+1))
        printf("even");
    else
        printf("odd");

    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
aman
  • 33
  • 2
  • 2
    while it doesn't matter in this case since `%` and `+` hav higher precedence than `?` , you should always enclose the macro's arguments in parentheses when you use them. See this answer for why: https://stackoverflow.com/a/29248016/1212725 – bruceg Aug 03 '17 at 02:09
  • 2
    @bruceg It _does_ matter that `%` has higher precedence than `+` which renders `x%2?0:1` a problem with `ODD(a+1)` – chux - Reinstate Monica Aug 03 '17 at 02:28
  • 1
    Why is the macro called `ODD` if it is supposed to return true on even? – Ajay Brahmakshatriya Aug 03 '17 at 03:21
  • 1
    @AjayBrahmakshatriya OP's output is certain to reflect the odd/even-ness of `a`. With the `a+1`, the text output is reversed. This is an exercise in the value of `()` in macros arguments. – chux - Reinstate Monica Aug 03 '17 at 13:37
  • @chux you're right. The % gets applied before the +, which is why you always enclose your macro's arguments in parentheses!!! – bruceg Aug 03 '17 at 17:34

4 Answers4

3

1 is treated as true and 0 as false.
if (1) is executed always, and when you get 0 as result, the branch shifts to else

so code should be :

if ODD is true (returning 1 from terneray expression), print "odd"

Urvashi Soni
  • 279
  • 1
  • 3
  • 13
3

ODD(a+1) expands to a+1%2?0:1. With a as 5, that is same as (5+(1%2))?0:1 or 0.
% beats + which beats ?:

if(0)
    printf("even");
else
    printf("odd");  // print `odd`

Perhaps you wanted some () to insure evaluation order.

// #define ODD(x) x%2?0:1
#define ODD(x) ((x)%2?0:1)

Yet that seems backwards. How about

#define ISODD(x) ((x)%2 != 0)

See How do I check if an integer is even or odd?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1
#define ODD(x) x % 2 ? 0 : 1

Given an even number x, x % 2 will give you zero, which is false.

Hence the result of the entire ternary expression will be the second option 1, which is true.

You would be better off with something like:

#define ODD(x) (((x) % 2) != 0)

It's both more readable in intent, and less prone to errors such as getting the true/false values mixed up, or being burnt by simple text substitution having unexpected effects.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1
  1. I do not like this kind if macros for many reasons (one of it that they can be a source of silly errors - like in your case). It should be domain of functions.

    int ODD(int x)
    {
       return x & 1;
    }
    

if you are worried about function call overhead just make it inline (but on any level op optimisation the compiler will inline it anyway as the call is probably longer than the function itself.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • `x & 1` report odd-ness incorrectly for negative values using the rare [Ones' complement](https://en.wikipedia.org/wiki/Ones%27_complement). – chux - Reinstate Monica Aug 03 '17 at 13:38
  • @chux and it is so important that you had to mention it - as this system has stopped to be used before I was born (note that I am in my 50), and am not worried too much if it works on CDC, UNIVAC or PDP-1 – 0___________ Aug 03 '17 at 13:51
  • [Is one's complement a real-world issue,...](https://stackoverflow.com/q/161797/2410359) goes into the relevancy issue. – chux - Reinstate Monica Aug 03 '17 at 13:53
  • I still do not care about univac machines. No one uses this system any more in the new designs (actually in the last 50+ years). So it is a retro mainframe computers issue only, not having any practical value. BTW waht about ENIAC? I have not found any information about the format used by this computer. – 0___________ Aug 03 '17 at 13:59