I tried to run this code,
int *p;
float q;
q = 6.6;
p = &q;
Though it will be a warning, but i think &q
and p
You're getting undefined behaviour, because you're passing the wrong types to printf
. When you tell it to expect a float, it actually expects a double
- but you pass an int
.
As a result it prints the wrong information, because printf
relies entirely on the format string to access the arguments you pass it.
In addition to what is said by teppic,
Consider,
int a = 5;
int *p = &a;
In this case we indicate to the compiler that p
is going to point to an integer. So it is known that when we do something like *p
, at runtime, the no. of bytes equal to size of an int
would be read.
If you assign address of a datatype occupying x
number of bytes to a pointer of which is declared to hold the address of datatypes of fewer bytes than x
, you read the wrong number of bytes when using the indirection operator.
You need to take compiler warnings more seriously.
C doesn't require compilers to reject invalid programs, it merely requires "diagnostics" for rule violations. A diagnostic can be either a fatal error message or a warning.
Unfortunately, it's common for compilers to issue warnings for assignments of incompatible pointer types.
void main()
This is wrong; it should be int main(void)
. Your compiler may let you get away with it, and it may not cause any visible problems, but there's no point in not writing it correctly. (It's not quite that simple, but that's close enough.)
int *p;
float q;
q = 6.6;
That's ok.
p = &q;
p
is of type int*
; &q
is of type float*
. Assigning one to the other (without a cast) is a constraint violation. The simplest way to look at it is that it's simply illegal.
If you really want to do this assignment, you can use a cast:
p = (int*)&q; /* legal, but ugly */
but there's rarely a good reason to do so. p
is a pointer to int
; it should point to an int
object unless you have a very good reason to make it point to something else. In some circumstances, the conversion itself can have undefined behavior.
printf("*p = %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
The %f
format requires a double
argument (a float
argument is promoted to double
in this context so float
would be ok). But *p
is of type int
. Calling printf
with an argument of the wrong type causes your program's behavior to be undefined.
%p
requires an argument of type void*
, not just of any pointer type. If you want to print a pointer value, you should cast it to void*
:
printf("&q = %p\n", (void*)&q);
It's likely to work without the cast, but again, the behavior is undefined.
If you get any warnings when you compile a program, don't even bother running it. Fix the warnings first.
As for the question in your title, pointers of type int*
and float*
are of different types. An int*
should point to an int
object; a float*
should point to a float
object. Your compiler may let you mix them, but the result of doing so is either implementation-defined or undefined. The C language, and particularly many C compilers, will let you get away with a lot of things that don't make much sense.
The reason that they're distinct types is to (try to) prevent, or at least detect, errors in their use. If you declare an object of type int*
, you're saying that you intend for it to point to an int
object (if it's not a null pointer). Storing the address of a float
object in your int*
object is almost certainly a mistake. Enforcing type safety allows such mistakes to be detected as early as possible (when your compiler prints a warning rather than when your program crashes during a demo for an important client).
It's likely (but not guaranteed) that int*
and float*
are the same size and have the same internal representation. But the meaning of an int*
object is not "a collection of 32 (or 64) bits containing a virtual address", but "something that points to an int
object".