user3857354
user3857354

Reputation:

Difference between (float *) & *(float*) in C

I am trying to understand the pointer concepts in-depth. In the following code,

#include <stdio.h>
int main()
{
    int i = 10;
    int *iptr = &i;
    printf("(float)* : %f\n", (float)*iptr);
    printf("(float*) : %f\n", (float*)iptr);
    printf("*(float*) : %f\n", *(float*)iptr);
    return 0;
}

output:

 (float)* : 10.000000
 (float*) : 10.000000
*(float*) : 0.000000

I also got a warning for the type-cast (float*).
I find it difficult to even analyse the difference. If anyone can help me to analyse what is the exact usage of all three, it would be helpful.

Upvotes: 0

Views: 12570

Answers (2)

tmlen
tmlen

Reputation: 9090

The first one is correct.

i is an int variable, and iptr a pointer to that int.

  1. (float)*iptr: *iptr dereferences iptr, which returns an int. Then that int is converted to a temporary float containing the same value. And that float is used by printf.

  2. *(float*)iptr: Attempts to cast a pointer-to-int into a pointer-to-float. This is invalid, and should produce a compiler warning or error. It creates a pointer with the same address, but with the type saying that it points to a float value.

    The * operator then dereferences it, so the int is read as if it were a float. So the resulting float would be invalid, and it could result in a segfault because floats are longer than ints, so it reads more memory than there is allocated for the int.

  3. (float*)iptr: Same problem, but it doesn't dereference the (invalid) pointer, and passes a pointer-to-float into printf, instead of a float. But printf expects a float. Some compilers should also produce a warning/error here because the format string indicates what value types are expected.

    If the format specifier indicates %p, it expects a pointer (void*, float*, or any other). It will then print out the address, and not the value it points to. This can be useful in debugging for example.

Upvotes: 3

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53016

The difference is

  1. You are dereferencing the int and casting it to float in

    printf("(float)* : %f\n", (float)*iptr);
    

    which is fine.

  2. You are casting the int pointer to a float pointer, and printing the float pointer with the "%f" specifier is undefined behavior, the correct specifier for printing pointers is "%p", so

    printf("(float*) : %f\n", (float*)iptr);
    

    is wrong, it should be

    printf("(float*) : %p\n", (void *) iptr);
    

    casting to float * here is not meaningful, because the void * address is the same as the float * address and also the int * address, the difference would be when you do pointer arithmetic.

  3. You are casting the int pointer to a float and dereferencing the resulting float pointer, although it will violate strict aliasing rules in

    printf("(float*) : %f\n", *(float*)iptr);
    

    which is also undefined behavior

Upvotes: 3

Related Questions