Search code examples
cc-preprocessorfractions

Issue with multiplication by a fraction in pre-processor Substitution (#define)


I'd like to start with the code

#define myConst (419*0.9)
#define myConst1 (419*.9)
#define myConst9 (myConst1*.9)
#define myConst11 (419*1.1)

int main()
{
    printf("myConst:%d\n",myConst);
    printf("myConst1:%d\n",myConst1);
    printf("myConst9:%d\n",myConst9);
    printf("myConst11:%d\n",myConst11);
    return 0;
}

Which gave me the output as

myConst:1913895624
myConst1:1
myConst9:1
myConst11:1

I'm unaware about why multiplication by a fraction in #define is leading to a different value than expected? And also the value of myConst is varying continuously for example, some value I observed are -254802840 -1713343480 466029496. And also myConst1,myConst9 and myConst11 are giving me 1, which isn't logical according to me.

Any explanation regarding the same is most welcome.


Solution

  • The #define has no role in this; the problem is that you are passing a double when printf is expecting an int (due to the %d specifier); technically that is undefined behavior, so anything is allowed to happen.

    Now, if this was built on 32 bit x86 probably you would get an int reinterpretation of the lower 32 bits of you float, since all parameters are normally passed on the stack. But I guess this is running on 64 bit x86, where parameters are passed in different registers if they are floating point. In this case, printf is just reading whatever garbage happens to be in some register at this time, there's not much logic involved in those values.

    Notice that almost any compiler can warn you about this kind of mismatch between format string and values actually passed. For gcc and clang I suggest you to enable this warning (-Wformat, included in -Wall, which you should definitely enable), and possibly mark it as an actual error (-Werror=format), as there's no legitimate reason to do a broken printf like this.