Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

void pointer = int pointer = float pointer

I have a void pointer pointing to a memory address. Then, I do

  • int pointer = the void pointer

  • float pointer = the void pointer

and then, dereference them go get the values.

{
    int x = 25;

    void   *p  = &x;
    int    *pi = p;
    float  *pf = p;
    double *pd = p;

    printf("x: n%d\n", x);
    printf("*p: %d\n", *(int *)p);
    printf("*pi: %d\n", *pi);
    printf("*pf: %f\n", *pf);
    printf("*pd: %f\n", *pd);

    return 0;
}

The output of dereferencing pi(int pointer) is 25. However the output of dereferencing pf(float pointer) is 0.000. Also dereferncing pd(double pointer) outputs a negative fraction that keeps changing?

Why is this and is it related to endianness(my CPU is little endian)?

like image 942
MAA Avatar asked Dec 21 '15 16:12

MAA


2 Answers

As per C standard, you'er allowed to convert any pointer to void * and convert it back, it'll have the same effect.

To quote C11, chapter §6.3.2.3

[...] A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

That is why, when you cast the void pointer to int *, de-reference and print the result, it prints properly.

However, standard does not guarantee that you can dereference that pointer to be of a different data type. It is essentially invoking undefined behaviour.

So, dereferencing pf or pd to get a float or double is undefined behavior, as you're trying to read the memory allocated for an int as a float or double. There's a clear case of mismtach which leads to the UB.

To elaborate, int and float (and double) has different internal representations, so trying to cast a pointer to another type and then an attempt to dereference to get the value in other type won't work.

Related , C11, chapter §6.5.3.3

[...] If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

and for the invalid value part, (emphasis mine)

Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.

like image 123
Sourav Ghosh Avatar answered Nov 06 '22 01:11

Sourav Ghosh


In addition to the answers before, I think that what you were expecting could not be accomplished because of the way the float numbers are represented.

Integers are typically stored in Two's complement way, basically it means that the number is stored as one piece. Floats on the other hand are stored using a different way using a sign, base and exponent, Read here.

So the main idea of convertion is impossible since you try to take a number represented as raw bits (for positive) and look at it as if it was encoded differently, this will result in unexpected results even if the convertion was legit.

like image 37
antonpuz Avatar answered Nov 06 '22 02:11

antonpuz