First, let me clarify that I know passing pointers as arguments to these printf
specifiers is not correct. I am interested however in knowing what is going on in printf
when it is done.
Using the normal print specifiers, %d
for int
, and %f
for float
, why is it the int *
prints, while the float *
will not?
For example, given these variables (unitialized):
int a, *pA;
float b, *pB;
pA = &a;
pB = &b;
When called like this:
void printVar(int *a, float *b)
{
printf("%d\n", a);//why does "a" print at all?
printf("%d %p\n", a, b);// when "b" prints only using %p
//printf("%d %f", a, b);// but fails on parameter mismatch using %f
printf("%d %f\n" , *a, *b);// prints normally (as expected)
}
Why do I get this?: ("a" prints OK, but "b" prints only with %p or by passing *b)
[edit] entire code to clarify and address some of the comment questions:
#include <ansi_c.h>
void printVar(int *a, float *b)
{
printf("%d\n", a);//why does "a" print at all?
printf("%d %p\n", a, b);// when "b" prints only using %p
//printf("%d %f", a, b);// but fails on parameter mismatch using %f
printf("%d %f\n" , *a, *b);// prints normally (as expected)
}
int main()
{
int a, *pA;
float b, *pB;
char s[100], *pS;
pA = &a;
pB = &b;
pS = &s[0];
printVar(pA, pB);
getchar();
return 0;
}
***[edit 2] addressing some comments about actual content if uncomment 3rd printf
I get the following two run-time notices, then get no output for the printf in line 3:
You have these parameters:
int *a, float *b
This:
printf("%d\n", a);
most likely treats the memory space occupied by a
(which is of type int*
) as if it were an object of type int
. On many systems, that will give you an almost meaningful result. (Of course if you really want to print a pointer value, you need to cast it to void*
and use %p
, but you're asking about the behavior of your incorrect code, not how to fix it.)
Things can get strange if int
and int*
are not the same size, or if int
s and pointers are passed differently as arguments (some CPUs have had dedicated address and/or floating-point registers, for example).
printf("%d %p\n", a, b);
It's very likely that void*
and float*
have the same representation, though that's not guaranteed by the language. If int
and int*
happen to be the same size, and are passed using the same argument-passing convention, this will most likely print the contents of the pointer a
as if it were an int
object, and then print the value of b
as a pointer.
//printf("%d %f", a, b);// but fails on parameter mismatch using %f
"%f"
requires an argument of type double
, not of type float
(float
arguments are promoted to double
for variadic functions like printf
). If int
and int*
are the same size, and double
and float*
are the same size, and all these types are passed using the same argument-passing convention, then this will most likely print the value of the pointer object a
as if it were an int
, and the value of the pointer object b
as if it were a double
object. The latter is likely to give you floating-point value that's completely garbage, perhaps even a NaN or Infinity. But if any of these assumptions fail, printf
will likely grab data off the stack (or from registers) in some order that may or may not match up with the argument values.
Every one of the above printf
calls has undefined behavior, which means that, strictly speaking, you should have no expectations about what will happen -- even that the behavior is in any way consistent. Understanding what's going on under the covers can be useful in recognizing the cause of an error (ah, that garbage floating-point value looks similar to what I got when I messed up a format string last month), but not really for anything else.
printf("%d %f\n" , *a, *b);// prints normally (as expected)
Ah, that's more like it -- but if this is executed after the previous calls, their undefined behavior may mess things up so badly that even this doesn't work. Also, looking at your entire program, the variables a
and b
in main
(whose addresses are passed to printVar
) are not initialized, so even in the best case *a
and *b
are garbage. Thanks to haccks for pointing this out in a comment.