0

I am trying to understand why the following code does not work... please help:

void incme(double *p)
{
    printf("%x,%x\n",p,*p);
    *p = *p + 1;
    printf("%x,%x\n",p,*p);
}
int main()
{
    int i = 1;
    incme((double *)&i);    
    printf("%x,%x",&i,i);
}

the output is:

ff99a348,1
ff99a348,1
ff99a348,1

I am expecting: ff99a348,1 ff99a348,2 ff99a348,2
it breaks everything I know about pointers...

Thanks.

EDIT:

the main question i am asking the the type cast in incme((double *)&i); why isit not casting it to double and pass it to the function ? ... sorry for not pointing out eailer ....

user1998844
  • 449
  • 8
  • 18

3 Answers3

3

Because of undefined behavior. Integers are not floating point, and floating point is not integers. Besides that, I think you will find that sizeof(int) != sizeof(double).

You're also breaking the strict aliasing rule.


Unrelated to your question, you should use the "%p" format if you want to print pointers.

Community
  • 1
  • 1
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • the type cast in incme((double *)&i); will to cast the int to double ? – user1998844 Aug 12 '15 at 08:41
  • @user1998844 No, it will cast a pointer to `int` to pointer to `double`. Integer values and floating point values are not encoded in the same way in computers, integers are stored as is in ther binary form while floating point values usually uses [IEEE754](https://en.wikipedia.org/wiki/IEEE_floating_point) encoding. – Some programmer dude Aug 12 '15 at 08:51
  • @user1998844 Besides that, because of the size difference and depending on machine [endianness](https://en.wikipedia.org/wiki/Endianness) you could be writing to unallocated memory in your function. – Some programmer dude Aug 12 '15 at 08:53
2

When you do *p = *p + 1; with p beeing a double* there is a lot going under the hood, indeed, double are represented using a custom format (wiki), when you use printf to display it as a integer after that, the internal representation of the memory at this address has changed (to a double representation), this is why you obtain such a result.

I ran the code and obtained the following output:

205afc2c,205afd28
205afc2c,593b4ab0
205afc2c,0

It shows use that the value is invalid as a double, and when it's incremented, it does not update the sizeof(int) first bits of the double (as it print 0 in the last line).

Hope I made myself clear !

Edit

I changed the code a little to show you what actually happen:

void incme(double *p)
{
    printf("%x,%lf\n",p,*p);
    *p = *p + 1;
    printf("%x,%lf\n",p,*p);
}
int main()
{
    int i = 1;
    incme((double *)&i);    
    printf("%x, %lf, %d",&i,i, i);
}

Gives me the following output:

cb90990c,0.000000
cb90990c,1.000000
cb90990c, 1.000000, 0

As you can see, if you print them as double, the value is indeed correct (but the binary representation of 1.0000 is not 00000000001 as I said previously, this is why the hex formatting gives you a large number). Back in the main, if you display the value as a double (event if i is supposed to be a int) as the incme function changed the memory layout of it, it does print 1.0000, but the first 32bits of the memory at this address are 0 hence, printing it as an int gives you 0.

ex0ns
  • 1,116
  • 8
  • 19
  • so the type cast at the function wont cast the i to double ? – user1998844 Aug 12 '15 at 08:43
  • It does cast it but as they do not have the same size or memory layout when you cast `int 1` to double, it gives you 0 because as a double it gives you a exponent of 0 (see the wikipedia page linked), and when you increment it, you get a 1 (in double representation, on 64bits) and thoses bits are lost when you print it back as an integer. – ex0ns Aug 12 '15 at 08:52
0

The main reason, the printf statements should read -

printf( "%p,%f", p, *p );

This will show your increment of the double.

Also - as stated, an int is generally 4 bytes and a double uses 8 bytes. (on most systems)

Neil
  • 1,036
  • 9
  • 18