Date: Sat, 6 Feb 1999 02:01:55 +0000 (GMT) From: Terry Lambert <tlambert@primenet.com> To: Matthew.Alton@anheuser-busch.com (Alton, Matthew) Cc: Hackers@FreeBSD.ORG Subject: Re: C headers Message-ID: <199902060201.TAA25935@usr02.primenet.com> In-Reply-To: <31B3F0BF1C40D11192A700805FD48BF90177670F@STLABCEXG011> from "Alton, Matthew" at Feb 5, 99 06:39:36 pm
next in thread | previous in thread | raw e-mail | index | archive | help
> Why does printf() non need #include <stdio.h> like the man page says? > A student asked me why and I can't explain this inconsistency. If you can explain symbol decoration in C++ objects, you can explain why ANSI C requires prototypes in scope, not necessarily for compilation and linking to succeed, but for proper function. Header files are only needed if you require a prototype in scope to deal with type promotion issues. In general, the only C code that needs prototypes in scope is code where the type promotion is not to type "int". For most general purpose computer architectures (e.g., ones which implement function arguments with promotion to int and passing on the stack), this is not a problem. For functions that accept/return types larger than "int" (i.e., where "int" would represent a demotion in size), you will run into problems. Such functions include any of the functions or system calls that take an off_t argument (for example: lseek). You will also run into problems with functions that take structure pointers or return them (example: stat), since the structure will not be defined without the header files. You can see similar promotion related problems that ANSI failed to address in the printf(3) function call. Specifically, examine the output of: #include <stdio.h> main() { long long q_num = -3; long l_num = -3; int i_num = -3; short s_num = -3; char c_num = -3; printf( "a signed quad -3 is: %qx\n", q_num); printf( "a signed long -3 is: %lx\n", l_num); printf( "a signed int -3 is: %x\n", i_num); printf( "a signed short -3 is: %hx\n", s_num); printf( "a signed char -3 is: %x\n", c_num); } The type promotion results in a sign extension error. Probably the proper connection would be to provide a "b" (for "byte") modifier to the "x" and "X" types, e.g.: printf( "a signed char -3 is: %bx\n", num); But using prototypes is actually a kludge around the fact that the declaration and usage information is not stored in the symbol definition for the function in the object file format, since if it were, failure to abide by calling conventions could be caught at link time, and would not have required complicating the language (there are arguments that "C++ will replace C, so making the code compilable with C++, which *demands* prototypes, is good"; people who don't buy into C++ replacing C don't buy this argument). Like "decorated" symbols in C++ works around the lack of class attribution and overloading information in the object format, so prototypes in scope in C files are meant to work around the lack of argument and return type information for C functions. So the fact that you will potentially get undetectable errors if you compile without a prototype in scope can really be blamed on lazy compiler writers who didn't want to update their linker technology at the same time that they were adding assumptions to their compiler. Anyway, use the header files, and use the warning flags (they should probably default "on", but I'll bet the compiler won't compile if you do that 8-)). Terry Lambert terry@lambert.org --- Any opinions in this posting are my own and not those of my present or previous employers. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199902060201.TAA25935>