-2

What am I doing wrong I always get intpart equal to 0 when I enter any number ?

#include <stdio.h>
#include <math.h>

int main(int argc, char* argv[])
{
double x=0.,fraction=0.;
int intpart=0;
printf("read value of x :");
scanf("%lf",&x);
fraction=modf(x,&intpart);
printf("x=%f    intpart=%d   fraction=%f \n",x,intpart,fraction);
return 0;
}
rondino
  • 395
  • 2
  • 3
  • 10

1 Answers1

2

modf() takes double* as its second argument. But you are passing an int*. So, it's undefined behaviour. The solution is to use a double*:

Change

int intpart=0;

to

double iptr = 0;

Compile with all warnings enabled. Clang produces the warning:

warning: incompatible pointer types passing 'int *' to parameter of type 'double *' [-Wincompatible-pointer-types]

and gcc produces:

warning: passing argument 2 of ‘modf’ from incompatible pointer type [-Wincompatible-pointer-types]

See C11 draft, 7.12.6.12, The modf functions.

Community
  • 1
  • 1
P.P
  • 117,907
  • 20
  • 175
  • 238
  • can you give that part in the standard stating that please ? what about casting double to int why it didn't work ? – rondino Aug 02 '16 at 13:22
  • 1
    @rondino Show us where you think you cast any `double` to `int`. If you mean 'why doesn't the compiler infer what I really want and cast for me', then thankfully, because it isn't so presumptuous. – underscore_d Aug 02 '16 at 13:24
  • 1
    If you mean casting an `int*` to `double*` then no, it'll create aliasing problems. Why not simply use the right type and declare `intptr` as `double`: `double iptr;`? – P.P Aug 02 '16 at 13:26
  • I do that only for educational purposes ! :) I will be really grateful if yougive me that part in the standard about your last comment ! – rondino Aug 02 '16 at 13:30
  • 1
    @rondino The fact that pointers aren't implicitly converted - and with the exception of _to_ `char *` can't be explicitly converted and dereferenced - follows from the facts that (A) different pointers may have different representations, and (B) trying to access an object of one type via a pointer of another violates strict aliasing rules; see http://stackoverflow.com/a/7005988/2757035 More directly: `double *` and `int *` are different, incompatible types. The compiler will not automatically realise what you _really_ want and fix your code and/or cast between pointer types and cause aliasing. – underscore_d Aug 02 '16 at 13:34
  • @underscore_d thanks a lot for the explanation ! same for P.P :) – rondino Aug 02 '16 at 13:49
  • 2
    @rondino You're welcome! It's great that you want to check the Standard! Btw, there's a thread on here somewhere that links to the final drafts of various C (and C++) versions in PDF form. I like to save these and text-search through them when looking for information, which sometimes works surprisingly well considering how big they are. ;-) – underscore_d Aug 02 '16 at 13:53