-2

I'm at a loss to understand how typecasting works with pointers

double x = 0.7;
int *ptr = (int *)&x;

What is happening with *(byte )&x ? &x means the address of variable x. Then what does typecasting an address mean? Can now ptr also refer to x? And if yes then don't we lose data?

Also what is the size of ptr ?

Dubby
  • 1,154
  • 3
  • 16
  • 31
  • Casting this to an int pointer doesn't make sense, because you are losing information. Double is 8 bytes and int 4. About the size, A pointer to anything is using 4 or 8 bytes depending on the architecture, 32 or 64 bit. – Montaldo Jun 12 '14 at 10:58
  • Are you onto the Quake fast inverse square root? If not you might find this very interesting. [Q_rsqrt](http://en.wikipedia.org/wiki/Fast_inverse_square_root). basically type punning only works if the memory layout if the same, and for int and float it doesn't since they use a different memory layout. – Montaldo Jun 12 '14 at 11:10
  • Do you know that `(byte *)&x` and `*(byte )&x ` are two different things? You seem to use them as identical. – this Jun 12 '14 at 11:37

2 Answers2

1

The line takes the address of the variable x and stores it's value to ptr. You have to cast the assignment because that assignment of double* to int* is not allowed.

By dereferencing ptr after the assignment you violate aliasing rules and cause your program to display undefined behavior.

Size of ptr is equal to the result from sizeof( ptr ) or sizeof( int* ) expression.

this
  • 5,229
  • 1
  • 22
  • 51
  • I wouldn't call it undefined behavior. Because if you cast it back to the original type the information is still there. This type punning is actually very common and used in socket programming all the time. – Montaldo Jun 12 '14 at 11:30
  • You don't have to, but standard does. Casting back to original type has nothing to do with this question and answer. The fact is that using ptr is undefined behavior as I have described. – this Jun 12 '14 at 11:33
0

Lets refactor your code a little bit:

#include <stdio.h>
#include <stdlib.h>


int main (void)
{
    int i;
    double d = 0.7;
    unsigned char* c = (unsigned char*)&d;

    for (i = 0; i < sizeof(d); i++) {
        printf("%x ", c[i]);
    }

    unsigned int* n = (unsigned int*) &d;

    printf("\n%x", *n);

    return 0;
}

The program above outputs something like this:

$ ./test.exe
66 66 66 66 66 66 e6 3f
66666666

Then what does typecasting an address mean? Can now ptr also refer to x? And if yes then don't we lose data?

Basically what you do is that you take &d which is a double* and convert it to an int*. By doing that you are interpreting whatever resides in memory at the &d into an int. It's not a simple matter of typecasting a double to an int but rather reinterpret the whole memory layout. This may have different outputs on different machines depending on their architecture (32/64 bits) and endianess.

dragosht
  • 3,237
  • 2
  • 23
  • 32
  • if I define something as `int i = 42; *((float *) &i) = 3.14;` What will this mean? – Dubby Jun 12 '14 at 11:32
  • It means you write 3.14 at the address of the i variable (overwriting its content). – dragosht Jun 12 '14 at 11:33
  • i mean could you go over it step by step? starting with innermost &i declaration and outwards? – Dubby Jun 12 '14 at 11:34
  • &i is the address of i (of type int*). You take this and convert it to a (float*). Then you dereference this float* pointer writing something in there. Since you used it as a float the internal binary representation of it will be float-like (as in IEEE 754 float http://en.wikipedia.org/wiki/IEEE_floating_point) – dragosht Jun 12 '14 at 11:38
  • @Dubby Don't forget that doing that in your code will cause your program exhibit undefined behavior, which will probably cause your program to crash randomly. – this Jun 12 '14 at 11:41