Dvir Naim
Dvir Naim

Reputation: 335

why to cast pointers?

I have a little basic question about C pointers and casting.
I didn't understand why should I cast the pointers?

I just tried this code and I got the same output for each option:

#include <stdio.h>

int main(void)
{
    int x = 3;
    int *y = &x;
    double *s;

    option 1: s = (double*)y;
    option 1: printf("%p, %d\n", (int*)s, *((int*)s));
    option 2: s = y;
    option 2: printf("%p, %d", s, *s);

    return 0;
}

My question is why do I have to do: s = (double*)y?
Intuitively, the address is the same for all the variables. The difference should be about how many bytes to read from this address. Also, about the printing - if I use %d it will take automatically as an int.

Why do I need to cast it as an int*?
Am I wrong?

Upvotes: 1

Views: 554

Answers (2)

chqrlie
chqrlie

Reputation: 144951

There is a great deal of confusion in your question. int and double are different things: they represent numbers in memory using different bit patterns and in most cases even a different number of bytes. The compiler produces code that converts between these representations when you implicitly or explicitly require that:

int x = 3;
double d;

d = x;          // implicit conversion from integer representation to double
d = (double)x;  // explicit conversion generates the same code

Here is a more subtle example:

d = x / 2;      // equivalent to d = (double)(x / 2);

will store the double representation of 1 into d. Whereas this:

d = (double)x / 2;  // equivalent to d = (double)x / 2.0;

will store the double representation of 1.5 into d.

Casting pointers is a completely different thing. It is not a conversion, but merely a coertion. You are telling the compiler to trust you know what you are doing. It does not change the address they point to, not does it affect the bytes in memory at that address. C does not let you store a pointer to int into a pointer to double because it is most likely an error: When you dereference the pointer using the wrong type, the content of memory is interpreted the wrong way, potentially yielding a different value or even causing a crash.

You can override the compiler's refusal by using an explicit cast to (double*), but you are asking for trouble.

When you later dereference s, you may access invalid memory and the value read is definitely meaningless.

Further confusion involves the printf function: the format specifiers in the format string are promisses by the programmer about the actual value types he passes as extra parameters.

printf("%p,%d",s,*s)

Here you pass a double (with no meaningful value) and you tell printf you passed an int. A blatant case of multiple undefined behaviour. Anything can happen, including printf producing similar output as the other option, leading to complete confusion. On 64 bit Intel systems, the way doubles and ints are passed to printf is different and quite complicated.

To avoid this kind of mistake in printf, compile with -Wall. gcc and clang will complain about type mismatches between the format specifiers and the actual values passed to printf.

As others have commented, you should not use pointer casts in C. Even the typical case int *p = (int *)malloc(100 * sizeof(int)) does not require a cast in C.

Upvotes: 6

i486
i486

Reputation: 6573

Explicit pointer casting is necessary to avoid compiler warnings. And compiler warnings on pointer type conflict exist to show possible bugs. With pointer casting you tell the compiler: "I know what I am doing here..."

Upvotes: 0

Related Questions