I am doing some exercises from book "Understanding pointers in C". The book gives you a piece of code and asks you for what you get in output.
One of them is the following:
#include <stdio.h>
int main(int argc, char* argv[])
{
char c, *cc;
int i;
long l;
float f;
c = 'Z';
i = 15;
l = 77777;
f = 3.14;
cc = &c;
printf("c=%c cc=%u\n", *cc, cc);
cc = &i;
printf("i=%d cc=%u\n",*cc,cc);
cc=&l;
printf("l=%ld cc=%u\n",*cc,cc);
cc=&f;
printf("f=%f cc=%u\n",*cc,cc);
return 0;
}
and the output is:
c=Z cc=1946293623
i=15 cc=1946293616
l=4294967249 cc=1946293608
f=0.000000 cc=4294967235
I don't understand why l and f are not printed as 77777 and 3.14?
I checked the book The C Programming Language to see if the if the printf's control chars are correct, and they are.
As Bryan's answer says, the types of the arguments passed to printf need to match the types specified by the format string.
The format to print a pointer value is "%p" -- and it expects a void* argument; a pointer of another type should be explicitly cast to void*.
Your program has undefined behavior because of the type mismatches. It also has constraint violations because it attempts to assign incompatible pointer types without a cast; cc = &i; is illegal (but a compiler can merely warn about it if it chooses). You should have gotten several warnings from your compiler.
I hope the intent of that program is to demonstrate what not to do. Let's consider just the last two lines before the return statement:
cc=&f;
printf("f=%f cc=%u\n",*cc,cc);
cc = &f; violates a constraint and requires a diagnostic (IMHO a good compiler should give you a fatal error and reject the program). &f is of type float*, and cc is of type char*; those types are not assignment-compatible.
Most compilers that accept that statement assume it implies an implicit conversion, making it equivalent to the legal but tricky:
cc = (char*)&f;
This causes cc to point to the first byte of the float object f.
printf("f=%f cc=%u\n",*cc,cc);
This claims to print the value of f, but it doesn't; it prints the value of the char object that cc points to, which happens to be the first byte of f. And it uses a %f format for that char object, which has undefined behavior. The result is garbage.
I was going to write a "corrected" version of that program, but it has so many problems, I couldn't figure out just what it's intended to do.
I checked the book The C programming language to see if the if the printf's control chars are correct, and they are.
No, they aren't. "%f" is correct for printing a float or double argument (float is promoted to double in this context), but you're passing a char argument.
This would be correct:
printf("*cc = %d, cc = %p\n", *cc, (void*)cc);
but it doesn't do the same thing; it prints the char pointed to by cc as an int (you could use %c to print it as a character, but it's likely to be unprintable), and then prints the value of cc as a pointer.
It would be interesting to see what the book says about this program.
The format specifiers of printf (and worse so scanf) have to match the types passed as parameters. If you are using GCC then use the -Wall option and it will also give warnings about this. Your code should look like this:
printf("c=%c cc=%u\n", *cc, (unsigned int)cc);
cc = &i;
Taking the address of i into a char* interpretation doesn't make sense anymore and neither does it for the others below. By assigning pointers, you enforce a wrong interpretation of the same bit representation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With