C printing EOF in c.

When I print EOF with
Code:
printf("%.4f", EOF);
it displays 0.0000 but when I do the same with
Code:
printf("%d", EOF);
it displays -1. Why is this?

thanks.
 
Well,
Code:
printf("%.4f", -1);
displays 0.0000 as well ;-)
There is something behind it, see e.g. this, which is referencing this paper.

However,
Code:
printf("%.4f", (float)EOF);
outputs -1.0000.
 
Did you any warnings? I get this helpful notice from the compiler
Code:
c.c:16:19: warning: format specifies type 'double' but the argument has type 'int' [-Wformat]

stdio.h et al included?
Juha
 
By default e.g. gcc version 5.4.0 (FreeBSD Ports Collection) ...

This is perhaps a special personal default setting. Since the OP informed neither the OS nor the complier version, the general default assumption must be FreeBSD 11.0-RELEASE and FreeBSD clang version 3.8.0. Consider the following test source file EOF.c:
Code:
#include <stdio.h>

int main(int argc, const char *argv[])
{
   printf("%.4f", EOF);
   return 0;
}
Code:
# cc EOF.c && ./a.out
EOF.c:5:19: warning: format specifies type 'double' but the argument has type 'int' [-Wformat]
   printf("%.4f", EOF);
           ~~~~   ^~~
           %.4d
/usr/include/stdio.h:201:13: note: expanded from macro 'EOF'
#define EOF     (-1)
                ^~~~
1 warning generated.
0.0000
 
This is perhaps a special personal default setting.
I use gcc in FreeBSD very rarely, definitely didn't change the defaults.
My point is that people who come to FreeBSD from Linux traditionally use gcc.
That's why I tried a small example right away and didn't get warnings from gcc!
 
sorry. I am running freebsd 9.1. and compiling with cc.

I tried to update to freebsd 11 but I am new to freebsd and couldn't figure out how to get it to work.
 
When I print EOF with
Code:
printf("%.4f", EOF);
it displays 0.0000 but when I do the same with
Code:
printf("%d", EOF);
it displays -1. Why is this?

thanks.

Because EOF is an int. When you use a format code for an int, you get the right output. The clang error message above is very descriptive and even tells you how to fix it. (Yay, clang!)
 
printf(3) is a variadic C function and its (mis)use is not dictated by language syntax or compiler beyond function call syntax. As such, you can pass printf(3) as many arguments as you want of any type and won't typically be punished for it by the compiler. Although your program will crash or print out garbage, or worse, it could print out reasonable output that you won't know is bogus without lots of debugging!

EOF is a #define for integer -1. You're telling printf(3) that you passed a float! As a consequence, printf(3) interprets the 4 bytes that you passed as though it were a float. And through IEEE754, the raw bits that define -1 as integer is somehow equivalent to 0 when the raw bits are interpreted as IEEE754 single precision.

Sometimes compilers will specially inspect printf(3) calls and generate warnings or cast your arguments for you. Otherwise, you promise that the substitution literals are the same as the types you passed to printf(3)!

Moral of the story? Use those substitution literals carefully and precisely. If you're not sure of the argument's type or which substitution literal to use, cast to a known type. Didn't know EOF wasn't a float?

Code:
printf("%.4f", (float)EOF);

This is the right way to do it.

Or better yet, use C++ and std::cout avoids this issue entirely!

References:
stdarg(3) -- How printf(3) really works.
/usr/include/inttypes.h -- #defines for substitution literals for stdint(7) integer typedefs.
https://en.wikipedia.org/wiki/IEEE_floating_point
https://en.wikipedia.org/wiki/Single-precision_floating-point_format
 
Back
Top